Proses Sinkronisasi Pembahasan Background Problem CriticalSection Sinkronisasi Hardware
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 n 1 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 next. Produced; while (1) { while (counter == BUFFER_SIZE) ; /* do nothing */ buffer[in] = next. Produced; in = (in + 1) % BUFFER_SIZE; counter++; }
Bounded-Buffer (3) • Consumer process item next. Consumed; while (1) { while (counter == 0) ; /* do nothing */ next. Consumed = 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 : register 1 = counter register 1 = register 1 + 1 counter = register 1 • Statement “count--” diimplementasikan dalam bahasa mesin : register 2 = counter register 2 = register 2 – 1 counter = register 2
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 : register 1 = counter (register 1 = 5) producer : register 1 = register 1 + 1 (register 1 = 6) consumer : register 2 = counter (register 2 = 5) consumer : register 2 = register 2 – 1 (register 2 = 4) producer : counter = register 1 (counter = 6) consumer : counter = register 2 (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 , P 0 and P 1 • Struktur umum dari proses adalah Pi (proses lain P j) 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, 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 Test. And. Set(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 n Permasalahan : bagaimana jika dua proses berbeda, yaitu produsen dan konsumen, berusaha mengakses buffer tersebut dalam waktu bersamaan. In. P 8 Buffers Producer Out. P 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[In. P] = c In. P = In. P + 1 mod n count++ } } n-1 0 1 … 2 thread consumer { while(1){ while (count==0) { no_op } c = buf[Out. P] Out. P = Out. P + 1 mod n count-// Consume char } } Global variables: char buf[n] int In. P = 0 // place to add int Out. P = 0 // place to get int count
Solusi Menggunakan Semaphore Global variables semaphore full_buffs = 0; semaphore empty_buffs = n; char buff[n]; int In. P, Out. P; 0 thread producer { 1 while(1){ 2 // Produce char c. . . 3 down(empty_buffs) 4 buf[In. P] = c 5 In. P = In. P + 1 mod n 6 up(full_buffs) 7 } 8 } 0 thread consumer { 1 while(1){ 2 down(full_buffs) 3 c = buf[Out. P] 4 Out. P = Out. P + 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 num. Waiting: int = 0 Barber Thread: while true Wait(customers) Lock(lock) num. Waiting = num. Waiting-1 Signal(barbers) Unlock(lock) Cut. Hair() end. While Customer Thread: Lock(lock) if num. Waiting < CHAIRS num. Waiting = num. Waiting+1 Signal(customers) Unlock(lock) Wait(barbers) Get. Haircut() else -- give up & go home Unlock(lock) end. If
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) end. While Reader Thread: while true Lock(mut) rc = rc + 1 if rc == 1 Wait(db) end. If Unlock(mut). . . Read shared data. . . Lock(mut) rc = rc - 1 if rc == 0 Signal(db) end. If Unlock(mut). . . Remainder Section. . . end. While
SEKIAN. . .
- Slides: 53