630 likes | 1.15k Views
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
E N D
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 di-increment 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 + 1counter = register1 Statement “count--” diimplementasikan dalam bahasa mesin : register2 = counterregister2 = register2 – 1counter = 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
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 dieksekusi dalam critical section tersebut
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
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 progres
Algoritma 3 (1) Flag untuk meminta ijin masuk Setiap proses menge-set sebuah flag untuk meminta ijin masuk. Lalu setiap proses men-toggle 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) 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... Critical section untu n proses :
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 Producer and consumer are separate threads InP Producer 8 Buffers OutP Consumer • Permasalahan : bagaimana jika dua proses berbeda, yaitu produsen dan konsumen, berusaha mengakses buffer tersebut dalam waktu bersamaan.
Is this a valid solution? • thread consumer { • while(1){ • while (count==0) { • no_op • } • c = buf[OutP] • OutP = OutP + 1 mod n • count-- • // Consume char • } • } • thread producer { • while(1){ • // Produce char c • while (count==n) { • no_op • } • buf[InP] = c • InP = InP + 1 mod n • count++ • } • } n-1 0 Global variables: char buf[n] int InP = 0 // place to add int OutP = 0 // place to get int count 1 2 …
Solusi Menggunakan Semaphore • 0 thread consumer { • while(1){ • down(full_buffs) • c = buf[OutP] • OutP = OutP + 1 mod n • up(empty_buffs) • // Consume char... • } • 8 } Global variables semaphore full_buffs = 0; semaphore empty_buffs = n; char buff[n]; int InP, OutP; • 0 thread producer { • while(1){ • // Produce char c... • down(empty_buffs) • buf[InP] = c • InP = InP + 1 mod n • up(full_buffs) • 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] // only called with mutex set! test(int i) { if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING){ state[i] = EATING; signal(sem[i]); } } take_forks(int i) { wait(mutex); state [i] = HUNGRY; test(i); signal(mutex); wait(sem[i]); }
Procedure Meletakkan Garpu int state[N] semaphore mutex = 1 semaphore 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]); } } put_forks(int i) { wait(mutex); state [i] = THINKING; test(LEFT); test(RIGHT); signal(mutex); }
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 Jika kursi tunggu penuh, tinggalkan toko
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 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 Barber Thread: while true Wait(customers) Lock(lock) numWaiting = numWaiting-1 Signal(barbers) Unlock(lock) CutHair() endWhile
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.