Today’s Agenda  Quick Review  Semaphore and Lock Advanced Topics in Software Engineering 1.

Slides:



Advertisements
Similar presentations
Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
Advertisements

– R 7 :: 1 – 0024 Spring 2010 Parallel Programming 0024 Recitation Week 7 Spring Semester 2010.
Practice Session 7 Synchronization Liveness Deadlock Starvation Livelock Guarded Methods Model Thread Timing Busy Wait Sleep and Check Wait and Notify.
Ch 7 B.
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Operating Systems CMPSC 473 Mutual Exclusion Lecture 13: October 12, 2010 Instructor: Bhuvan Urgaonkar.
6.5 Semaphore Can only be accessed via two indivisible (atomic) operations wait (S) { while S
Monitors Chapter 7. The semaphore is a low-level primitive because it is unstructured. If we were to build a large system using semaphores alone, the.
COSC 3407: Operating Systems Lecture 8: Semaphores, Monitors and Condition Variables.
Classical Problems of Concurrency
02/19/2010CSCI 315 Operating Systems Design1 Process Synchronization Notice: The slides for this lecture have been largely based on those accompanying.
Avishai Wool lecture Introduction to Systems Programming Lecture 4 Inter-Process / Inter-Thread Communication.
5.6 Semaphores Semaphores –Software construct that can be used to enforce mutual exclusion –Contains a protected variable Can be accessed only via wait.
Chapter 6: Process Synchronization. Outline Background Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores Classic Problems.
Chapter 6: Process Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts – 7 th Edition, Feb 8, 2005 Objectives Understand.
Process Synchronization
Monitors CSCI 444/544 Operating Systems Fall 2008.
1 School of Computing Science Simon Fraser University CMPT 300: Operating Systems I Ch 6: Process Synchronization Dr. Mohamed Hefeeda.
02/25/2004CSCI 315 Operating Systems Design1 Process Synchronization Notice: The slides for this lecture have been largely based on those accompanying.
Chapter 6: Process Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts – 7 th Edition, Feb 8, 2005 Module 6: Process Synchronization.
More Synchronisation Last time: bounded buffer, readers-writers, dining philosophers Today: sleeping barber, monitors.
Operating Systems CSE 411 CPU Management Oct Lecture 13 Instructor: Bhuvan Urgaonkar.
CS4231 Parallel and Distributed Algorithms AY 2006/2007 Semester 2 Lecture 2 (19/01/2006) Instructor: Haifeng YU.
Chapter 6: Process Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts – 7 th Edition, Feb 8, 2005 Background Concurrent.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Classical problems.
6.3 Peterson’s Solution The two processes share two variables: Int turn; Boolean flag[2] The variable turn indicates whose turn it is to enter the critical.
Critical Problem Revisit. Critical Sections Mutual exclusion Only one process can be in the critical section at a time Without mutual exclusion, results.
Operating Systems CMPSC 473 Mutual Exclusion Lecture 14: October 14, 2010 Instructor: Bhuvan Urgaonkar.
Semaphores, Locks and Monitors By Samah Ibrahim And Dena Missak.
4061 Session 21 (4/3). Today Thread Synchronization –Condition Variables –Monitors –Read-Write Locks.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
Concurrency: Mutual Exclusion and Synchronization Chapter 5.
Silberschatz, Galvin, and Gagne  Applied Operating System Concepts Module 7: Process Synchronization Background The Critical-Section Problem.
Chap 6 Synchronization. Background Concurrent access to shared data may result in data inconsistency Maintaining data consistency requires mechanisms.
Today’s Agenda  Quick Review  Monitor Advanced Topics in Software Engineering 1.
1 Interprocess Communication (IPC) - Outline Problem: Race condition Solution: Mutual exclusion –Disabling interrupts; –Lock variables; –Strict alternation.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Synchronization.
Today’s Agenda  HW #2 Out  Replay Semaphore and Lock  Advanced Locking Advanced Topics in Software Engineering 1.
Chapter 6: Process Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Background The.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
CSC 360 Instructor: Kui Wu More on Process Synchronization Semaphore, Monitor, Condition Variables.
6.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts with Java – 8 th Edition Module 6: Process Synchronization.
Dining Philosophers & Monitors Questions answered in this lecture: How to synchronize dining philosophers? What are monitors and condition variables? What.
Silberschatz, Galvin and Gagne ©2013 Operating System Concepts – 9 th Edition Chapter 5: Process Synchronization.
Semaphores Chapter 6. Semaphores are a simple, but successful and widely used, construct.
6.1 Silberschatz, Galvin and Gagne ©2005 Operating System Principles 6.5 Semaphore Less complicated than the hardware-based solutions Semaphore S – integer.
Deadlock and Starvation
CS703 - Advanced Operating Systems
Semaphore Synchronization tool that provides more sophisticated ways (than Mutex locks) for process to synchronize their activities. Semaphore S – integer.
Chapter 5: Process Synchronization – Part 3
Auburn University COMP 3500 Introduction to Operating Systems Synchronization: Part 4 Classical Synchronization Problems.
Chapter 5: Process Synchronization – Part II
Deadlock and Starvation
Monitors, Condition Variables, and Readers-Writers
Advanced Topics in Software Engineering 1
Chapter 6: Process Synchronization
Chapter 6: Process Synchronization
Chapter 5: Process Synchronization (Con’t)
Monitors Chapter 7.
Lecture 25 Syed Mansoor Sarwar
Semaphore Originally called P() and V() wait (S) { while S <= 0
Module 7a: Classic Synchronization
Chapter 7: Synchronization Examples
Semaphores Chapter 6.
Monitors Chapter 7.
Monitors Chapter 7.
Presentation transcript:

Today’s Agenda  Quick Review  Semaphore and Lock Advanced Topics in Software Engineering 1

Quick Review  What are the differences between a binary semaphore and a lock? Advanced Topics in Software Engineering 2

Advanced Topics in Software Engineering 3 Semaphore and Locks  Introduction  Semaphore Implementation  Semaphore and Locks in Java  Semaphore-based Solutions

Advanced Topics in Software Engineering 4 Motivation Earlier solutions to the critical section problem, like Peterson’s algorithm, are quite complex, error prone, and inefficient. We need to have a better solution so that the problem can be solved in a more disciplined way.

Advanced Topics in Software Engineering 5 Semaphore A semaphore is a synchronization construct that can be used to provide mutual exclusion and conditional synchronization. From another perspective, a semaphore is a shared object that can be manipulated only by two atomic operations, P and V.

Advanced Topics in Software Engineering 6 Counting & Binary Semaphores There are two types of semaphores: Counting Semaphore and Binary Semaphore. Counting Semaphore can be used for mutual exclusion and conditional synchronization. Binary Semaphore is specially designed for mutual exclusion.

Advanced Topics in Software Engineering 7 Counting Semaphore A counting semaphore can be considered as a pool of permits. A thread uses P operation to request a permit. If the pool is empty, the thread waits until a permit becomes available. A thread uses V operation to return a permit to the pool.

Advanced Topics in Software Engineering 8 An OO Definition A counting semaphore can be defined in an object- oriented manner as shown below: class CountingSemaphore { private int permits; public CoutingSemaphore (int initialPermits) { permits = initialPermits; } public void P() {... } public void V() {... } }

Advanced Topics in Software Engineering 9 An Implementation Sketch Here is a sketch of one possible implementation of methods P() and V(): public void P() { permits = permits – 1; if (permits < 0) { wait on a queue of blocked threads; } public void V() { ++ permits; if (permits <= 0) { notify one waiting thread; }

Advanced Topics in Software Engineering 10 Invariant For a counting semaphore s, at any time, the following condition holds: (the initial number of permits) + (the number of completed s.V operations) ≥ (the number of completed s.P operations.

Advanced Topics in Software Engineering 11 Binary Semaphore A binary semaphore must be initialized with 1 or 0, and the completion of P and V operations must alternate. If the semaphore is initialized with 1, then the first completed operation must be P. If the semaphore is initialized with 0, then the first completed operation must be V. Both P and V operations can be blocked, if they are attempted in a consecutive manner.

Advanced Topics in Software Engineering 12 Counting vs. Binary Semaphore Counting Semaphore Can take any initial value V operation never blocks Completed P and V operations do not have to alternate V could always be the first completed operation Binary Semaphore Can only take 0 or 1 Both P and V operation may block Completed P and V operations must alternate If the initial value is 0, the first completed operation must be V; if the initial value is 1, the first completed operation must be P.

Advanced Topics in Software Engineering 13 Simulating Counting Semaphores public final class CountingSemaphore { private int permits = 0; BinarySemaphore mutex (1); BinarySemaphore delayQ (0); public CoutingSemaphore (int initialPermits) { permits = initialPermits; } public void P () { mutex.P ();(1) -- permits;(2) if (permits < 0) {(3) mutex.V ();(4) delayQ.P ();(5) } else mutex.V ();(6) } public void V () { mutex.P ();(7) ++ permits;(8) if (permits <= 0) {(9) delayQ.V ();(10) } mutex.V ();(11) }

Advanced Topics in Software Engineering 14 A scenario T1T2T3T4 (1) (2) (3) (4) (1) (2) (3) (4) (7) (8) (9) (10) (7) (8) (9) *(10) (5) *(10) (5)

Advanced Topics in Software Engineering 15 Lock Lock is another synchronization construct that can be used to solve the critical section problem. A lock defines two types of operations: lock and unlock.

Advanced Topics in Software Engineering 16 Lock Ownership A lock can be owned by at most one thread at any given time. A thread that calls lock becomes the owner of a lock if the lock is not owned by any other thread; otherwise, the thread is blocked. The owner of a lock can release the ownership by calling unlock. Important: The owner of a lock is not blocked if it calls lock again. However, the owner must call unlock the same number of times to release the ownership.

Advanced Topics in Software Engineering 17 Lock vs. Binary Semaphore For a binary semaphore, consecutive P operations will be blocked. But a thread that owns a lock can invoke lock operations again without being blocked. The owner for calls to lock and unlock must be the same thread. But calls to P and V can be made by different threads.

Advanced Topics in Software Engineering 18 Lock vs. Binary Semaphore Lock l = new Lock (); BinarySemaphore s = new BinarySemaphore (1); T1: l.lock();... T1: s.P();... T1: l.lock(); T2: l.unlock(); T1: s.P(); T2: s.V();

Advanced Topics in Software Engineering 19 synchronized method public synchronized void foo () { this.lock ();... bar ();... this.unlock (); } public synchronized void bar () { this.lock ();... this.unlock (); } public synchronized void foo () { this.P ();... bar ();... this.V (); } public synchronized void bar () { this.P ();... this.V (); } Each object has a lock.Each object has a BinarySemaphore.

Advanced Topics in Software Engineering 20 Binary Semaphore vs. Lock Binary Semaphore Has no concept of ownership Any thread can invoke P or V operations Consecutive P (or V) operations will be blocked Need to specify an initial value Lock A lock can be owned by at most one thread at any given time Only the owner can invoke unlock operations The owner can invoke lock (or unlock) operations in a row. Does not have to be initialized

Advanced Topics in Software Engineering 21 Semaphore  Introduction  Semaphore Implementation  Semaphore in Java  Semaphore-based Solutions

Advanced Topics in Software Engineering 22 Implementation 1 public void P() { while (permits == 0) { sleep (interval); } permits = permits – 1; } public void V() { permits = permits + 1; }

Advanced Topics in Software Engineering 23 Implementation 2 public void P() { permits = permits – 1; if (permits < 0) { wait on a queue of blocked threads; } public void V() { permits = permits + 1; if (permits <= 0) { notify one waiting thread; }

Advanced Topics in Software Engineering 24 Implementation 3 public void P() { if (permits == 0) { wait on a queue of blocked threads; } permits = 0; if (queue of threads blocked in V() is not empty) { awaken one waiting thread in V(); } public void V() { if (permits == 1) { wait on a queue of blocked threads; } permits = 1; if (queue of threads blocked in P() is not empty) { awaken one waiting thread in P(); }

Advanced Topics in Software Engineering 25 Mutual exclusion for permits public void P() { entry-section; permits = permits – 1; if (permits < 0) { exit-section; wait on a queue of blocked threads; entry-section; } exit-section; } public void V() { entry-section; permits = permits + 1; if (permits <= 0) { notify one waiting thread; } exit-section; }

Advanced Topics in Software Engineering 26 VP Operation Let s and t be two semaphores. An execution of t.VP(s) is equivalent to s.V(); t.P(); except that during the execution of t.VP(s), no intervening P(), V() or VP() operations are allowed to be completed on s and t.

Advanced Topics in Software Engineering 27 VP Operation (Cont’d) Thread 1 Thread 2 s.V() t.P() t.P() Thread 1 Thread 2 t.VP(s) t.P() Consider the following two program fragments:

Advanced Topics in Software Engineering 28 Semaphore  Introduction  Semaphore Implementation  Semaphore in Java  Semaphore-based Solutions

Advanced Topics in Software Engineering 29 Abstract Definition Java does not provide any semaphore classes. We can however simulate semaphores in Java. public abstract class Semaphore { protected int permits; protected abstract void P(); protected abstract void V(); protected Semaphore (int initialPermits) { permits = initialPermits; } }

Advanced Topics in Software Engineering 30 CountingSemaphore public final class CountingSemaphore extends Semaphore { public CoutingSemaphore (int initialPermits) { super(initialPermits;) } synchronized public void P () { permits --; if (permits < 0) { try { wait (); } catch (InterruptedException ex) {}; } synchronized public void V () { ++ permits; if (permits <= 0) { notify (); }

Advanced Topics in Software Engineering 31 BinarySemaphore public final class BinarySemaphore extends Semaphore { public BinarySemaphore (int initialPermits) { super(initialPermits); if (initialPermits != 0 || initialPermits != 1) { throw new IllegalArgumentException(“initial value must be 0 or 1.”); } synchronized public void P () { while (permits == 0) { try { wait (); } catch (InterruptedException ex) {}; } permits = 0; notifyAll (); } synchronized public void V () { while (permits == 1) { try { wait (); } catch (InterruptedException ex) {}; } permits = 1; notifyAll (); }

Advanced Topics in Software Engineering 32 BinarySemaphore (cont’d) If we replace “while” … “notifyAll” with “if” … “notify”, does it still implement BinarySemaphore correctly?

Advanced Topics in Software Engineering 33 MutexLock public final class MutexLock { private Thread owner = null; private int waiting = 0; public int count = 0; public boolean free = true; public synchronized void lock () { if (free) { count = 1; free = false; owner = Thread.currentThread (); } else if (owner == Thread.currentThread()) { ++ count; } else { ++ waiting; try { wait(); } catch (InterruptedException ex) {} free = false; count = 1; owner = Thread.currentThread () } public synchronized void unlock () { if (owner != null) { if(owner == Thread.currentThread ()) { -- count; if(count == 0) { owner = null; if (waiting > 0) { -- waiting; free = true; notify(); } else { free = true; return; } } else return; } throw new OwnerException (); }

Advanced Topics in Software Engineering 34 Semaphore  Introduction  Semaphore Implementation  Semaphore in Java  Semaphore-based Solutions

Advanced Topics in Software Engineering 35 The CS Problem The following simple solution applies to the general n-process CS problem. BinarySemaphore mutex = new BinarySemaphore (1); while (true) { mutex.P(); critical section mutex.V(); non-critical section }

Advanced Topics in Software Engineering 36 Resource Allocation (1) Consider there are three threads that contend for two resources: CountingSemaphore resources = new CoutingSemaphore (2); Thread 1Thread 2Thread 3 resources.P ();resources.P ()resources.P () /* use the resource *//* use the resource *//*use the resource*/ resources.V ();resources.V ()resources.V ()

Advanced Topics in Software Engineering 37 Resource Allocation (2) Many problems require bookkeeping to be done outside of P and V methods. int count = 2; int waiting = 0; CountingSemaphore mutex = new CountingSemaphore (1); CountingSemaphore resAvail = new CoutingSemaphore (0); /* before using a resource */ mutex.P (); if (count > 0) { count --; mutex.V (); } else { waiting ++; mutex.V (); resAvail.P (); } /* after using a resource */ mutex.P (); if (waiting > 0) { -- waiting; resAvail.V (); } else { count ++; } mutex.V ();

Advanced Topics in Software Engineering 38 Semaphore Patterns  Mutex: A binary semaphore or a counting semaphore initialized as 1.  Enter-and-Test: A thread needs to enter a critical section before testing a condition that involves shared variables.  Exit-before-Wait: A thread inside a critical section needs to release its mutual exclusion before it waits on a condition.  Condition queue: A semaphore can be used as a queue of blocked threads that are waiting for a condition to become true.

Advanced Topics in Software Engineering 39 The Bounded Buffer Problem There is a single producer and a single consumer; and there is a n-slot communication buffer. The producer deposits items into the buffer; the consumer fetches items from the buffer. A solution to this problem should not overwrite any item and/or fetch any item more than once. In addition, the solution should allow maximum concurrency.

Advanced Topics in Software Engineering 40 Solution 1 Item buf [] = new Item [n]; CountingSemaphore full = new CoutingSemaphore (0); CountingSemaphore empty = new CountingSemaphore (n); Producer { int in = 0; Item item;... empty.P ();(1) buf[in] = item;(2) in = (in + 1) % n;(3) full.V ();(4)... } Consumer { int out = 0; Item item;... full.P ();(5) item = buf[out];(6) out = (out + 1) % n;(7) empty.V ();(8)... }

Advanced Topics in Software Engineering 41 The Bounded Buffer Problem (Cont’d) Does solution 1 work if we have multiple producers and consumers?

Advanced Topics in Software Engineering 42 Solution 2 Item buf [] = new Item [n]; CountingSemaphore full = new CoutingSemaphore (0); CountingSemaphore empty = new CountingSemaphore (n); BinarySemaphore pMutex = new BinarySemaphore (1); BinarySemaphore cMutex = new BinarySemaphore (1); Producer { int in = 0; Item item;... empty.P(); pMutex.P(); buf[in] = item; in = (in + 1) % n; pMutex.V() full.V();... } Consumer { int out = 0; Item item;... full.P(); cMutex.P(); item = buf[out]; out = (out + 1) % n; cMutex.V(); full.V();... }

Advanced Topics in Software Engineering 43 Dining Philosophers Requirements: Absence of deadlock Absence of starvation Maximal Parallelism chopsticks[1] philosophers[1] chopsticks[0] chopsticks[2] chopsticks[3] chopsticks[4] philosophers[0] philosophers[4] philosophers[2] philosophers[3] rice

Advanced Topics in Software Engineering 44 Solution 1 BinarySemaphore chopsticks = new BinarySemaphore [n]; // initialization for (int j = 0; j < n; j ++) { chopsticks[j] = new BinarySemaphore (1); } philosopher i while (true) { /* think */ chopsticks[i].P();(1) chopsticks[(i + 1) % n].P();(2) /* eat */ chopsticks[i].V();(3) chopsticks[(i + 1) % n].V();(4) }

Advanced Topics in Software Engineering 45 Solution 2 This solution is the same as solution 1 except that only (n – 1) philosophers are allowed to sit at a table that has n seats.

Advanced Topics in Software Engineering 46 Solution 3 This solution is the same as solution 1 except that one philosopher is designated as the “odd” philosopher and this odd philosopher picks up her right fork, instead of her left fork, first.

Advanced Topics in Software Engineering 47 Solution 4 const int thinking = 0; const int hungry = 1; const int eating = 2; BinarySemaphore mutex(1); int state[] = new int [n]; BinarySemaphore self[] = new BinarySemaphore [n ]; for (int j = 0; j < n; j ++) { state[j] = thinking; self[j] = new BinarySemaphore (0); } philosopher i while (true) { /* think */ mutex.P(); state[i] = hungry; test(i); mutex.V(); self[i].P(); /* eat */ mutex.P(); state[i] = thinking; test((i – 1) % n); test((i + 1) % n); mutex.V(); } void test (int k) { if ((state[k] = hungry) && (state[(k - 1) % n] != eating) && (state[(k + 1) % n] != eating)) { state[k] = eating; self[k].V(); }

Advanced Topics in Software Engineering 48 Readers/Writers Problem Readers may access shared data concurrently, but a writer always has exclusive access. What’s the difference between readers/writers problem and producers/consumers problem?

Advanced Topics in Software Engineering 49 Access Strategies In general, there are three categories of access strategies:  R = W: Readers and writers have equal priority.  R > W: Readers generally have a higher priority than writers.  R < W: Readers generally have a lower priority than writers

Advanced Topics in Software Engineering 50 Access Strategies (cont’d)  R = W.1: One reader or one writer with equal priority.  R = W.2: Many readers or one writer with equal priority.  R > W.1: Many readers or one writer with readers having a higher priority.  R > W.2: Same as R > W.1 except that when a reader arrives, if no other reader is reading or waiting, it waits until all writers that arrived earlier have finished.  R < W.1: Many readers or one writer with writers having a higher priority.  R < W.2: Same as R < W.1 except that when a writer arrives, if no other writer is waiting or writing, it waits until all readers that arrived earlier have finished.

Advanced Topics in Software Engineering 51 R = W vs. R > W vs. R < W r1 w1r2w2 Consider the following request queue. Identify the order in which the requests will be served according to different access strategies.

Advanced Topics in Software Engineering 52 R > W.1 vs. R > W.2 Writer 1: Writer 2: Writer 3: Reader 1: req w1start w1end w1req w2req w3req r1

Advanced Topics in Software Engineering 53 R < W.1 vs. R < W.2 Writer 1: Reader 1: Reader 2: Writer 2: req w1 start w1end w1 req r1 req r2 req w2

Advanced Topics in Software Engineering 54 R > W.1 int activeReaders = 0, activeWriters = 0, waitingWriters = 0, waitingReaders = 0; BinarySemaphore mutex; CountingSemaphore readers_que(0), writer_que(0); read () { mutex.P ();(1) if (activeWriters > 0) {(2) waitingReaders ++;(3) readers_que.VP(mutex);(4) } activeReaders ++;(5) if (waitingReaders > 0) {(6) waitingReaders --;(7) readers_que.V();(8) } else { mutex.V ();(9) } /* read shared data */ mutex.P ();(10) activeReaders --;(11) if (activeReaders == 0 && waitingWriters > 0) { (12) waitingWriters --;(13) writers_que.V ();(14) } else { mutex.V ();(15) } write () { mutex.P (); if (activeReaders > 0 || activeWriters > 0) { waitingWriters ++; writers_que.VP(mutex); } activeWriters ++; mutex.V (); /* write shared data */ mutex.P (); activeWriters --; if (waitingReaders > 0) { waitingReaders --; readers_que.V (); } else if (waitingWriters > 0) { waitingWriters --; writers_que.V(); } else { mutex.V(); }

Advanced Topics in Software Engineering 55 R > W.2 int activeReaders = 0; MutexLock mutex; BinarySemaphore writers_r_que(1); read () { mutex.lock(); ++ activeReaders; if (activeReaders == 1) { writers_r_que.P(); } mutex.unlock (); /* read shared data */ mutex.lock (); -- activeReaders; if (activeReaders == 0) { writers_r_que.V (); } mutex.unlock (); } write () { writers_r_que.P(); /* write shared data */ writers_r_que.V(); }

Advanced Topics in Software Engineering 56 R < W.2 int activeReaders = 0; int waitingOrWritingWriters = 0; MutexLock mutex_r, mutex_w; BinarySemaphore writers_que(1), readers_w_que(1); read () { readers_w_que.P(); mutex_r.lock (); ++ activeReaders; if (activeReaders == 1) { writers_que.P(); } mutex_r.unlock (); readers_w_que.V(); /* read shared data */ mutex_r.lock (); -- activeReaders; if (activeReaders == 0) { writers_que.V (); mutex_r.unlock (); } write () { mutex_w.lock (); ++ waitingOrWritingWriters; if (waitingOrWritingWriters == 1) { readers_w_que.P (); } mutex_w.unlock (); writers_que.P(); /* write shared data */ writers_que.V(); mutex_w.lock(); -- waitingOrWritingWriters; if (waitingOrWritingWriters == 0) { readers_w_que.V(); } mutex_w.unlock (); }