240 likes | 721 Views
Concurrent Process Synchronization (Lock and semaphore). CSE 380 Lecture Note 5 Insup Lee. Locks. lock (x) performs lock: [ if x = false then x := true else go to lock ] unlock (x) performs [x := false ] E.g.,
E N D
Concurrent Process Synchronization(Lock and semaphore) CSE 380 Lecture Note 5 Insup Lee CSE 380
Locks • lock (x) performs • lock: [ if x = false then x := true else go to lock ] • unlock (x) performs • [x := false ] • E.g., • var x : booleanparbegin P1: ... lock(x); CS_1; unlock(x) … … Pn: ... lock(x); CS_n; unlock(x) …parend CSE 380
Properties • 1. Starvation is possible. • 2. Busy waiting. • 3. Different locks may be used for different shared resources. • 4. Proper use not enforced. E.g., forget to lock. CSE 380
How to implement locks • Requires an atomic (uninterruptable at the memory level) operations like test-and-set or swap. • atomicfunction TestAndSet (var x: boolean): boolean;begin TestAndSet := x; x := true;end • procedure Lock (var x : boolean);while TestAndSet(x) do skip od; • procedure Unlock (var x: boolean); x := false; • (1) If not supported by hardware, TestAndSet can be implemented by disabling and unabling interrupts.(2) Lock can also be implemented using atomic swap(x,y). CSE 380
Hardware Instructions • Examples: (1) VAX 11, (2) B6500 • MIPS -- Load-Linked/Store Conditional (LL/SC) • Pentium -- Compare and Exchange, Exchange, Fetch and Add • SPARC -- Load Store Unsigned Bit (LDSTUB) in v9 • PowerPC -- Load Word and Reserve (lwarx) and Store Word Conitional (stwcx) CSE 380
(1) VAX 11 • BBSSI Branch on Bit Set and Set Interlocked.BBCCI Branch on Bit Clear and Clear Interlocked. • op bitpos, var, displacement • Operation: teststate = if {BBSSI} then 1 else 0 {set interlock} tmp := bit bit := teststate {release interlock} if tmp = teststate then pc := pc + displacement fi • Busy waiting -- set bit and if already set then go to 1$ 1$: BBSSI bit, base, 1$ CSE 380
(2) B6500 • Read with lock operation.SPIN: If RDLK (x) then go to SPIN; • RDLK(x) • register memoryA: addr of x B: 1 <--------> x: • Swap the contents of B and x in one memory cycle and return B. CSE 380
Semaphores • P V Dijkstra ‘65 wait signal Per Brinch Hansen • The semaphore has a value that is invisible to the users and a queue of processes waiting to acquire the semaphore. • type semaphore = record value : integer; L : list of process; end • P(S):[ S.value := S.value-1; if S.value < 0 then add this process to S.L; block; end if ]V(S):[ S.value := S.value + 1; if S.value <= 0 then remove a process P from S.L; wakeup(P); end if ] CSE 380
Properties of semaphore • parbegin S.value = 1 P1: ... P(S); CS1; V(S); ... P2: ... P(S); CS2; V(S); ... . . . Pn: ... P(S); CSn; V(S); ...parend • Properties • No busy waiting • May starve unless FCFS (scheduling left to the implementer of semaphores) • Can handle multiple users by proper initialization. Example: 3 tape drivers • Can implement scheduling on an precedence graph. CSE 380
More properties and examples • e.g. P2 P1 P4 P3 P6 P5 • P1: Do Work P2: P(S12) P3: P(13) V(S12) Do Work Do Work V(S13) V(S24) V(S34) V(S35) • Proper use can't be enforced by compiler. • e.g. P(S) V(S) CS CS V(S) P(S) • e.g. S1, S2 • P1: P(S1) P2: P(S2) P(S2) P(S1) CS CS V(S2) V(S1) V(S1) V(S2) CSE 380
Classical problems • The bounded buffer problem • The readers and writers problems • The sleeping barber problem • The dining philosophers problem CSE 380
The Producer-Consumer Problem • bounded buffer (of size n) • one set of processes (producers) write to it • one set of processes (consumers) read from it • semaphore: full = 0 /* counting semaphores */ empty = n mutex = 1 /* binary semaphore */ • process Producer process Consumerdoforeverdoforever . P(full) /* produce */ P(mutex) • . /* take from buffer */ P(empty) V(mutex) P(mutex) V(empty) • /* add to buffer */ . V(mutex) /* consume */ V(full) .endend CSE 380
The Dining Philosopher Problem • Five philosopher spend their lives thinking + eating. • One simple solution is to represent each chopstick by a semaphore. • P before picking it up & V after using it. • var chopstick: array[0..4] of semaphores=1philosopher i • repeat P( chopstock[i] ); P( chopstock[i+1 mod 5] ); ... eat ... V( chopstock[i] ); V( chopstock[i+1 mod 5] ); ... think ...forever • Is deadlock possible? CSE 380
Number of possible states • 5 philosophers • Local state (LC) for each philosoper • thinking, waiting, eating • Glabal state = (LC 1, LC 2, …, LC5) • E.g., (thinking, waiting, waiting, eating, thinking) • E.g., (waiting, eating, waiting, eating, waiting) • So, the number of global states are 3 ** 5 = 243 • Actually, it is a lot more than this since waiting can be • Waiting for the first fork • Waiting for the second fork CSE 380
Number of possible behaviors • Sequence of states • Initial state: (thinking,thinking,thinking,thinking,thinking) • The number of possible behaviors = 5 x 5 x 5 x … • Deadlock state: (waiting,waiting,waiting,waiting, waiting) • Given the state transition model of your implementation, show that it is not possible to reach the deadlock state from the initial state. CSE 380
The Readers and Writers Problem Shared data to be accessed in two modes: reading and writing. • Any number of processes permitted to read at one time • writes must exclude all other operations. • Read WriteRead Y N conflictWrite N N matrix Intuitively: • Reader: | Writer:when(no_writers==0) do | when(no_readers==0 no_readers=no_readers+1 | and no_writers==0) do | no_writers = 1 | <read> | <write> | no_readers=no_readers-1 | no_writers = 0 . | . . | . CSE 380
A Solution to the R/W problem • Semaphore: mutex = 1 /* mutual excl. for updating readcount */ wrt = 1 /* mutual excl. writer */ • int variable: readcount = 0 • Reader: P(mutex) readcount = readcount + 1if readcount == 1 then P(wrt) V(mutex) <read> P(mutex) readcount = readcount – 1if readcount == 0 then V(wrt) V(mutex) • Writer: P(wrt) <write> V(wrt) • Notes: wrt also used by first/last reader that enters/exits critical section. Solution gives priority to readers in that writers can be starved by stream of readers. CSE 380
2nd assignment • Use semaphores • Need to have shared memory between processes to allocate semaphores CSE 380
Semaphores • A semaphore is a non-negative integer count and is generally used to coordinate access to resources • System calls: • int sema_init(sema_t *sp, unsigned int count, int type, void * arg): Initialize semaphores pointed to by sp to count. type can assign several different types of behavior to a semaphore • int sema_destroy(sema_t *sp); destroys any state related to the semaphore pointed to by sp. The semaphore storage space is not released. • int sema_wait(sema_t *sp); blocks the calling thread until the semaphore count pointed to by sp is greater than zero, and then it atomically decrements the count. CSE 380
Semaphores (cont’d) • int sema_trywait(sema_t *sp); atomically decrements the semaphore count pointed to by sp, if the count is greater than zero; otherwise, it returns an error. • int sema_post(sema_t *sp); atomically increments the semaphore count pointed to by sp. If there are any threads blocked on the semaphore,one will be unblocked. CSE 380
Example • The customer waiting-line in a bank is analogous to the synchronization scheme of a semaphore using sema_wait() and sema_trywait(): CSE 380
Semaphores example #include <errno.h> #define TELLERS 10 sema_t tellers; /* semaphore */ int banking_hours(), deposit_withdrawal; void *customer(), do_business(), skip_banking_today(); ... sema_init(&tellers, TELLERS, USYNC_THREAD, NULL); /* 10 tellers available */ while(banking_hours()) pthread_create(NULL, NULL, customer, deposit_withdrawal); ... void * customer(int deposit_withdrawal) { int this_customer, in_a_hurry = 50; this_customer = rand() % 100; CSE 380
if (this_customer == in_a_hurry) { if (sema_trywait(&tellers) != 0) if (errno == EAGAIN) { /* no teller available */ skip_banking_today(this_customer); return; } /* else go immediately to available teller and decrement tellers */ } else sema_wait(&tellers); /* wait for next teller, then proceed, and decrement tellers */ do_business(deposit_withdrawal); sema_post(&tellers); /* increment tellers; this_customer's teller is now available */ } CSE 380