Modul-7_Proses_Sinkronisasi

Download Report

Transcript Modul-7_Proses_Sinkronisasi

Proses Sinkronisasi
Pembahasan
•
•
•
•
•
•
Background
Problem Critical-Section
Sinkronisasi Hardware
Semaphore
Problem Klasik Sinkronisasi
Monitor
Background
• Akses secara bersamaan pada data yang di-sharing
mengakibatkan data menjadi inkonsistensi
• Maintain data yang konsisten membutuhkan
mekanisme untuk memastikan bahwa eksekusi proses
dari cooperating proses dilakukan secara berurutan
• Shared-memory solution to bounded-butter problem
(Chapter 4) allows at most n – 1 items in buffer at the
same time. A solution, where all N buffers are used is
not simple.
• Solusi shared-memory pada problem bounded-buffer
(Consumer-Producer) memungkinkan paling banyak n1 item dalam buffer pada waktu yang sama.
– Misal kita memodifikasi code producer-consumer dengan
menambahkan variabel counter, diinisialisasi 0 dan diincrement setiap ada item baru yang ditambahkan ke dalam
buffer
Bounded-Buffer (1)
• Shared data
#define BUFFER_SIZE 10
typedef struct {
...
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int counter = 0;
Bounded-Buffer (2)
• Producer process
item nextProduced;
while (1) {
while (counter == BUFFER_SIZE)
; /* do nothing */
buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
Bounded-Buffer (3)
• Consumer process
item nextConsumed;
while (1) {
while (counter == 0)
; /* do nothing */
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
}
Bounded-Buffer (4)
• Statement :
counter++;
counter--;
dijalankan secara atomic.
• Operasi atomic adalah operasi yang
menyelesaikan program didalamnya tanpa
interupsi.
Bounded-Buffer (5)
• Statement “count++” diimplementasikan dalam bahasa
mesin :
register1 = counter
register1 = register1 + 1
counter = register1
• Statement “count--” diimplementasikan dalam bahasa
mesin :
register2 = counter
register2 = register2 – 1
counter = register2
Bounded-Buffer (6)
• If both the producer and consumer attempt to
update the buffer concurrently, the assembly
language statements may get interleaved.
• Interleaving depends upon how the producer
and consumer processes are scheduled.
Bounded-Buffer (7)
• Misal counter diinisialisasi 5. Interleaving statemen
adalah :
producer : register1 = counter (register1 = 5)
producer : register1 = register1 + 1 (register1 = 6)
consumer : register2 = counter (register2 = 5)
consumer : register2 = register2 – 1 (register2 = 4)
producer : counter = register1 (counter = 6)
consumer : counter = register2 (counter = 4)
• Nilai counter bisa 4 atau 6, dimana seharusnya adalah
5.
Race Condition (1)
• Race condition : adalah situasi dimana
beberapa proses mengakses dan
memanipulasi data bersama pada saat yang
bersamaan. Nilai akhir dari data bersama
tersebut tergantung pada proses yang terakhir
selesai.
• Untuk mencegah race condition proses-proses
yang berjalan bersamaan harus disinkronisasi
(synchronized).
Contoh : Print Spooler
• Ketika sebuah proses ingin mencetak
sebuah berkas (file), proses tersebut
memasukkan nama berkas ke dalam
spooler direktori khusus. Proses lain,
printer daemon, secara periodik memeriksa
untuk mengetahui jika ada banyak berkas
yang akan dicetak, dan jika ada berkas
yang sudah dicetak dihilangkan nama
berkasnya dari direktori.
– Out = penunjuk berkas berikutnya untuk
dicetak
– In = menunjuk slot kosong di direktori
Race Condition (2)
Problem Critical-Section
• Bagian dari program dimana shared
memory diakses disebut critical section
atau critical region
• n proses berkompetisi untuk
menggunakan shared data
• Masing-masing memiliki code segment,
dinamakan critical section dimana shared
data diakses
• Problem : bagaimana memastikan satu
proses dieksekusi dalam critical section,
dan tidak ada proses lain yang boleh
Solusi Problem Critical-Section
(1)
4 kondisi solusi yang baik :
• Tidak ada dua proses secara bersamaan masuk
ke dalam critical section
• Tidak ada asumsi mengenai kecepatan atau
jumlah CPU
• Tidak ada proses yang berjalan di luar critical
section yang dapat mem-blok proses lain
• Tidak ada proses yang menunggu selamanya
untuk masuk critical section
Solusi Problem Critical-Section
(2)
• Mutual Exclusion. Jika proses Pi dieksekusi dalam
critical section, maka tidak ada proses lain dapat
dieksekusi dalam critical section tersebut.
• Progress. Artinya ketika tidak ada proses yang
menggunakan critical section dan ada proses-proses
yang ingin menggunakan critical section tersebut, maka
harus ada proses yang menggunakan critical section
tersebut.
• Bounded Waiting. Maksud dari Bounded Waiting
adalah setiap proses yang menunggu menggunakan
critical section, maka proses-proses yang menunggu
tersebut dijamin suatu saat akan menggunakan critical
section. Dijamin tidak ada thread yang mengalami
starvation : proses seolah-olah berhenti, menunggu
request akses ke critical section diperbolehkan.
Komponen Critical Section
• Entry section : kode yang digunakan untuk
masuk ke dalam critical section.
• Critical section : kode dimana hanya ada
satu proses yang dapat dieksekusi dalam
satu waktu.
• Exit section : akhir dari critical section,
mengijinkan proses lain.
• Remainder section : kode istirahat setelah
masuk ke critical section.
Aturan Critical-Section
Solusi yang diberikan harus memenuhi
permintaan berikut :
• Mutual exclusion
• Deadlock free
• Starvation free
Critical Region
Pendekatan Solusi Proses
Sinkronisasi
• Solusi Software
– Tanpa sinkronisasi
– Dengan sinkronisasi
• Low-level primitif : semaphore
• High-level primitif : monitors
• Solusi Hardware
Mutual Exclusion
• Tiga kondisi untuk menentukan mutual
exclusion :
– Tidak ada dua proses yang pada saat
bersamaan berada dalam critical region
– Tidak ada proses yang berjalan diluar critical
region yang bisa menghambat proses lain
– Tidak ada proses yang tidak bisa masuk ke
critical region
Cara Pemecahan Masalah
• Hanya dua proses , P0 and P1
• Struktur umum dari proses adalah Pi (proses lain
Pj)
do {
entry section
critical section
exit section
reminder section
} while (1);
• Proses-proses dapat share variabel untuk
sinkronisasi
Algoritma 1
• Shared variabel :
– int turn;
initially turn = 0
– turn = i  Pi dapat masuk ke dalam critical section
• Process Pi
do {
while (turn != i) ;
critical section
turn = j;
reminder section
} while (1);
• Memenuhi mutual exclusion, tapi tidak menuhi
progres
Algoritma 2 (1)
• Menggunakan flag untuk setiap proses dan
memeriksa flag proses yang lain dan tidak
akan masuk critical section bila ada proses
lain yang sedang masuk.
Algoritma 2 (2)
• Shared variabel :
– boolean flag[2];
initially flag [0] = flag [1] = false.
– flag [i] = true  Pi siap untuk masuk ke dalam critical
section
• Process Pi
do {
flag[i] := true;
while (flag[j]) ;
critical section
flag [i] = false;
remainder section
} while (1);
• Memenuhi mutual exclusion, tapi tidak menuhi
Algoritma 3 (1)
• Flag untuk meminta ijin masuk
– Setiap proses menge-set sebuah flag untuk
meminta ijin masuk. Lalu setiap proses mentoggle bit untuk mengijinkan proses yang lain
untuk yang pertama
• Kombinasi shared variabel algoritma 1 & 2
Algoritma 3 (2)
• Process Pi
do {
flag [i]:= true;
turn = j;
while (flag [j] and turn = j) ;
critical section
flag [i] = false;
remainder section
} while (1);
• Memenuhi ketiga persyaratan, memecahkan
masalah critical-section untuk kedua proses.
Algoritma Bakery (1)
Critical section untu n proses :
• Sebelum masuk ke dalam critical section, proses
menerima sebuah nomor. Pemegang nomor
yang terkecil masuk ke critical section.
• Jika ada dua proses atau lebih (Pi and Pj)
menerima nomor sama, maka proses dengan
indeks terkecil (i < j) yang dilayani lebih dulu
untuk masuk ke critical section. Misal Pi dilayani
lebih dulu, baru kemudian Pj.
• Skema penomoran selalu naik secara berurut,
contoh : 1,2,3,3,3,3,4,5...
Algoritma Bakery (2)
• Shared data
boolean choosing[n];
int number[n];
Struktur data masing-masing diinisialisai false
dan 0.
Algoritma Bakery (3)
• Algoritma
do {
choosing[i] = true;
number[i] = max(number[0], number[1], …, number [n –
1])+1;
choosing[i] = false;
for (j = 0; j < n; j++) {
while (choosing[j]) ;
while ((number[j] != 0) && (number[j,j] < number[i,i])) ;
}
critical section
number[i] = 0;
remainder section
} while (1);
Sinkronisasi Hardware
• Disabling Interrupt : hanya untuk uniprosesor
saja
• Atomic test and set : mengembalikan parameter
dan menge-set parameter ke atomic
• Test and modify the content of a word atomically
boolean TestAndSet(boolean &target) {
boolean rv = target;
tqrget = true;
return rv;
}
Semaphore (1)
• Semaphore adalah pendekatan yang
diajukan oleh Djikstra
• Prinsipnya dua proses atau lebih dapat
bekerjasama dengan menggunakan
penanda-penanda sederhana.
• Variabel khusus untuk penanda disebut
semaphore
Semaphore (2)
• Sifat-sifat semaphore
– Dapat diinisialisasi dengan nilai non-negatif
– Terdapat dua operasi : Down (Wait) dan Up
(Signal)
• Operasi Down dan Up adalah atomic, tak
dapat diinterupsi sebelum diselesaikan.
Semaphore – Operasi Down (Wait)
• Operasi ini menurunkan menilai
semaphore
– Jika nilai semaphore menjadi non-positif
maka proses yang mengeksekusinya di-block
Semaphore – Operasi Up (Signal)
• Operasi ini menaikkan menilai semaphore
– Jika satu proses atau lebih di-block pada
semaphore tidak dapat menyelesaikan
operasi Down, maka salah satu dipilih oleh
sistem dan menyelesaikan operasi Down-nya.
Pemilihan proses dilakukan secara acak.
Definisi Klasik Wait & Signal
Wait(S)
{
while S <= 0 do noop;
/* busy wait! */
S = S – 1;
/* S >= 0 */
}
Signal (S)
{
S = S + 1;
}
Implementasi Blocking pada
Semaphore
• Semaphore S memiliki nilai (S.val), dan suatu
thread list (S.list).
Wait (S) / Down(S)
S.val = S.val - 1
If S.val < 0
/* negative value of S.val */
{
add calling thread to S.list;
/* is # waiting threads */
block;
/* sleep */
}
Signal (S) / Up(S)
S.val = S.val + 1
If S.val <= 0
{
remove a thread T from S.list;
wakeup (T);
}
Problem Klasik pada Sinkronisasi
• Ada tiga hal yang selalu menjadi masalah
pada sinkronisasi :
– Problem Bounded Buffer
– Problem Dining Philosopher
– Problem Sleeping Barber
– Problem Readers and Writers
Problem Bounded Buffer

Permasalahan : bagaimana jika dua proses berbeda, yaitu
produsen dan konsumen, berusaha mengakses buffer
tersebut dalam waktu bersamaan.
InP
8 Buffers
Producer
OutP
Consumer
Producer and
consumer
are separate threads
Is this a valid solution?
thread producer {
while(1){
// Produce char c
while (count==n) {
no_op
}
buf[InP] = c
InP = InP + 1 mod n
count++
}
}
n-1
0
1
…
2
thread consumer {
while(1){
while (count==0) {
no_op
}
c = buf[OutP]
OutP = OutP + 1 mod n
count-// Consume char
}
}
Global variables:
char buf[n]
int InP = 0
// place to add
int OutP = 0 // place to get
int count
Solusi Menggunakan Semaphore
Global variables
semaphore full_buffs = 0;
semaphore empty_buffs = n;
char buff[n];
int InP, OutP;
0 thread producer {
1
while(1){
2
// Produce char c...
3
down(empty_buffs)
4
buf[InP] = c
5
InP = InP + 1 mod n
6
up(full_buffs)
7
}
8 }
0 thread consumer {
1
while(1){
2
down(full_buffs)
3
c = buf[OutP]
4
OutP = OutP + 1 mod n
5
up(empty_buffs)
6
// Consume char...
7
}
8 }
Problem Dining Philosophers
• Lima filosof duduk dalam satu meja
• Satu garpu terletak diantara
masing-masing filosof
• Saat makan membutuhkan 2 garpu
• Bagaimana mencegah deadlock ?
Each philosopher is
modeled with a thread
while(TRUE) {
Think();
Grab first fork;
Grab second fork;
Eat();
Put down first fork;
Put down second fork;
}
Is this a valid solution?
#define N 5
Philosopher() {
while(TRUE) {
Think();
take_fork(i);
take_fork((i+1)% N);
Eat();
put_fork(i);
put_fork((i+1)% N);
}
}
Procedure Mengambil Garpu
int state[N]
semaphore mutex = 1
semaphore sem[i]
take_forks(int i) {
wait(mutex);
state [i] = HUNGRY;
test(i);
signal(mutex);
wait(sem[i]);
}
// only called with mutex set!
test(int i) {
if (state[i] == HUNGRY &&
state[LEFT] != EATING &&
state[RIGHT] != EATING){
state[i] = EATING;
signal(sem[i]);
}
}
Procedure Meletakkan Garpu
int state[N]
semaphore mutex = 1
semaphore sem[i]
put_forks(int i) {
wait(mutex);
state [i] = THINKING;
test(LEFT);
test(RIGHT);
signal(mutex);
}
// only called with mutex set!
test(int i) {
if (state[i] == HUNGRY &&
state[LEFT] != EATING &&
state[RIGHT] != EATING){
state[i] = EATING;
signal(sem[i]);
}
}
Problem Sleeping Barber (1)
Problem Sleeping Barber (2)
• Barber :
– Ketika ada orang yang menunggu untuk potong
rambut, letakkan satu orang ke kursi, dan
memotong rambut
– Jika sudah selesai, pindah ke pelanggan
berikutnya
– Jika tidak ada pelanggan maka tidur, sampai
ada pelanggan yang datang
• Customer :
– Jika tukang potong rambut tidur, bangunkan
barber
– Jika ada orang yang sedang potong rambut,
tunggu barber dengan duduk di kursi tunggu
Design Solusi
• Bagaimana kita memodelkan barber dan
customer ?
• What state variables do we need?
• Variabel keadaan seperti apa yang kita
butuhkan ?
– .. dan yang mana di-share ?
– …. dan bagaimana kita akan memproteksinya ?
•
•
•
•
Bagaimana membuat barber tidur ?
Bagaimana membuat barber bangun ?
Bagaimana membuat customer menunggu ?
What problems do we need to look out for?
Is this a good solution?
const CHAIRS = 5
var customers: Semaphore
barbers: Semaphore
lock: Mutex
numWaiting: int = 0
Barber Thread:
while true
Wait(customers)
Lock(lock)
numWaiting = numWaiting-1
Signal(barbers)
Unlock(lock)
CutHair()
endWhile
Customer Thread:
Lock(lock)
if numWaiting < CHAIRS
numWaiting = numWaiting+1
Signal(customers)
Unlock(lock)
Wait(barbers)
GetHaircut()
else -- give up & go home
Unlock(lock)
endIf
Problem Readers and Writers
• Banyak reader dan writer ingin mengakses
suatu database yang sama (masing-masing satu
thread)
• Banyak reader dapat diproses secara
bersamaan
• Writer harus di-sinkronisasi dengan reader dan
writer yang lain
– Hanya satu writer pada satu waktu !
– Ketika seseorang ingin menulis, harus tidak ada
reader !
Tujuan :
– Memaksimumkan concurrency.
– Mencegah starvation.
Design Solusi
• Bagaimana membuat model readers dan
writers ?
• Bagaimana variabel keadaan yang kita
perlukan ?
– .. dan yang mana di-share ?
– …. dan bagaimana kita akan memproteksinya ?
•
•
•
•
Bagaimana membuat writers menunggu ?
Bagaimana membuat writer bangun ?
Bagaimana membuat readers menunggu ?
Bagaimana membuat readers bangun ?
Is this a valid solution to readers &
writers?
var mut: Mutex = unlocked
db: Semaphore = 1
rc: int = 0
Writer Thread:
while true
...Remainder Section...
Wait(db)
...Write shared data...
Signal(db)
endWhile
Reader Thread:
while true
Lock(mut)
rc = rc + 1
if rc == 1
Wait(db)
endIf
Unlock(mut)
... Read shared data...
Lock(mut)
rc = rc - 1
if rc == 0
Signal(db)
endIf
Unlock(mut)
... Remainder Section...
endWhile
SEKIAN ...