1 / 28

Synchronization II:

Synchronization II:. CPE 261403 - Operating Systems http://www.e-cpe.org/moodle. Classical Problems of Synchronization. Bounded-Buffer Problem (6.6.1) Dining-Philosophers Problem (6.6.3) (Readers-Writers Problem 6.6.2). How many orders does Amazon.com receives per day?. Peak day for 2008

conniemoore
Télécharger la présentation

Synchronization II:

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Synchronization II: CPE 261403 - Operating Systems http://www.e-cpe.org/moodle

  2. Classical Problems of Synchronization • Bounded-Buffer Problem (6.6.1) • Dining-Philosophers Problem (6.6.3) • (Readers-Writers Problem 6.6.2)

  3. How many orders does Amazon.com receives per day? Peak day for 2008 6.3M orders in one day ( = 72.9 orders per sec)

  4. Order Order Order Order Order Process & Ship Process & Ship Process & Ship Process & Ship Process & Ship

  5. Bounded-Buffer Problem Produce(Data) { // produce an item if (bufferLen < N) { Buffer[bufferLen] = Data bufferLen++; } } Consume() { // consume an item if (bufferLen > 0) { return Buffer[bufferLen--]; } } Consumer Producer What is the problem with this code?

  6. Bounded-Buffer Problem 1 0 N Semaphores Mutex Full Empty while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Consumer Producer

  7. Human Error is Hard to Debug

  8. Example of a simple human error 1 0 N Semaphores Mutex Full Empty while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer if (error) { exit(0); } signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Semaphore not properly set before exit Consumer Producer

  9. Correcting the error 1 0 N Semaphores Mutex Full Empty while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer if (error) { signal (mutex); signal (empty); exit(0); } signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Reset semaphores before exiting Consumer Producer

  10. Example II of a simple human error 1 0 N Semaphores Mutex Full Empty while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer if (error) { signal (mutex); signal (empty); if (just-a-warning) { warn-user; } if (critical Error) {exit(0); } } signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Producer and Consumer can become “Out of sync” because “Signal” may be run twice Consumer Producer

  11. Correcting the error 1 0 N Semaphores Mutex Full Empty while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer if (error) { if (just-a-warning) { warn-user; } if (critical Error) { signal (mutex); signal (empty); exit(0); } } signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Putting ‘signal’ in the right condition Consumer Producer

  12. Monitors • Higher level API than Semaphores • Can help prevent human error Figure 6.19

  13. Bounded Buffer Problem • monitorBoundedBuffer { • functionProduce (value) { • if BufferLen < N • // Add a value to Buffer • BufferLen++; • } • Function consume() { • If BufferLen > 0 • // remove a value from Buffer • BufferLen--; • } • } • // usage example • BoundedBuffer.Produce(x) • Output = BoundedBuffer.Consume() Functions in a Monitor is mutual exclusive by default Can use a simple variable instead of a counting semaphore

  14. Using “Conditions” to Sync Threads • monitorBoundedBuffer { • Condition content • Condition emptySpace • functionProduce (value) { • if BufferLen < N • // Add a value to Buffer • content.signal() • else • emptySpace.wait() • // Add a value to Buffer • } • Function consume() { • If BufferLen > 0 • // remove a value from Buffer • emptySpace.signal() • else • content.wait() • // remove a value from Buffer • } • } Wait conditions put the thread to sleep and releases the monitor to other threads. A “signal” wakes the thread.

  15. “Condition” properties • Condition.Wait() puts the process to sleep. • Condition.signal() wakes up exactly one process. If no process is waiting, then signal has no effect.

  16. Dining-Philosophers Problem Figure 6.16

  17. A solution using SemaphoresEvery philosopher runs this code While (true) { wait ( chopstick[i] ); wait ( chopStick[ (i + 1) % 5] ); // eat signal ( chopstick[i] ); signal (chopstick[ (i + 1) % 5] ); // think }

  18. Deadlock?

  19. Using Monitors monitor DP { enum { THINKING; HUNGRY, EATING) state [5] ; condition self [5]; void pickup (int i) { state[i] = HUNGRY; test(i); if (state[i] != EATING) self [i].wait; } void putdown (int i) { state[i] = THINKING; // test left and right neighbors test((i + 4) % 5); test((i + 1) % 5); }

  20. Using Monitors (Cont.) void test (int i) { if ( (state[(i + 4) % 5] != EATING) && (state[i] == HUNGRY) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING ; self[i].signal () ; } } initialization_code() { for (int i = 0; i < 5; i++) state[i] = THINKING; } }

  21. Readers Writers Problem (I) Readers Writers Writers Readers Writers Writers Readers Readers One at a time Concurrent Read DATA • Writers will wait for all readers to finish • Readers cannot read only when a writer is already running

  22. Readers Writers Problem Solution using Semaphore vs Monitor

  23. Semaphore Thread writer() { While (true) { Wait (wrt);// รอจนกว่าจะได้ semaphore wrt จึงจะเข้าไปเขียนข้อมูล // ทำการเขียนข้อมูลที่นี่ Signal (wrt); } }

  24. Thread reader() { While (true) { Wait (mutex); // ร้องขอ mutex เพราะมีการแปลงค่าตัวแปร readcount ถือเป็น critical section Readcount++; // นับว่ามี reader ทำงานอยู่กี่ตัว If (readcount == 1)// reader ที่เข้ามาตัวแรกจะยึด semaphore wrt ไว้ไม่ให้ writer ทำงาน Wait (wrt); Signal (mutex); // ทำการอ่านข้อมูลที่นี่ Wait (mutex);// มีการแปลงค่าตัวแปร ถือเป็น critical section เช่นเดียวกับข้างต้น Readcount--;// ลดจำนวนนับ reader ลง If (readcount == 0)// ถ้าไม่เหลือ reader แล้วก็ปล่อย semaphore wrt เพื่อให้ writer ทำงานได้ Signal (wrt); Signal(mutex); } }

  25. Using Monitors • Monitor RWProblem { • Void Read() { • // อ่านข้อมูล • } • Void Write() { • // เขียนข้อมูล • } • } Does this work? No. Because (1) No more than one reader can run at a time (2) We cannot control our policy (readers before writers)

  26. Monitor RWProblem { • int readcount=0; // ใช้นับว่ามี reader กี่ตัว • boolean busy = 0; • condition okToWrite; • condition okToRead; • void StartWrite() { • if ((readcount > 0) || (busy==1)) { okToWrite.wait() } • busy = 1; • } • Void EndWrite () { • busy = 0; • if okToRead.QueueCount > 0 { okToRead.signal(); } • else { okToWrite.signal(); } • } • void StartRead() { • if (busy) { okToRead.wait(); } • readcount++; // นับว่ามี reader ทำงานอยู่กี่ตัว • okToRead.signal();// ถ้า reader ได้ทำงานตัวหนึ่งแล้วตัวอื่นที่ wait อยู่ก็จะได้ทำงานด้วย • } • Void EndRead() { • readcount--; • If (readcount == 0){ okToWrite.signal();} • } • }

More Related