semaphores
play

Semaphores A counting semaphore s consists of a private integer value - PDF document

Concurrent programming slides T.S. Norvell (c) 2001 Semaphores A counting semaphore s consists of a private integer value s.c (invariant s.c 0 ) and three operations executed with mutual exclusion w.r.t. the others. Abstract de


  1. Concurrent programming slides T.S. Norvell (c) 2001 Semaphores A “counting semaphore” s consists of a private integer value s.c (invariant s.c ≥ 0 ) and three operations executed with mutual exclusion w.r.t. the others. Abstract de Þ nition ( initialize is called Þ rst and once): proc initialize( i : int ) ; pre i > = 0 c := i end initialize proc acquire % AKA P wait until c > 0 c -= 1 end acquire proc release % AKA V c += 1 end release 9

  2. Concurrent programming slides T.S. Norvell (c) 2001 You can think of a semaphore as a bowl containing c pebbles. • acquire: Remove one pebble from the bowl • release: Add one pebble to the bowl For mutual exclusion we use Global data and initialization: var s : semaphore ; s.initialize(1 ) ; acquire(i): s.acquire release(i): s.release 10

  3. Concurrent programming slides T.S. Norvell (c) 2001 Further Uses of Semaphores We can also use semaphores to implement other forms of coordination. For example a single buffer Messenger module which mimics the Messenger monitor we saw earlier. module Messenger ; export send, receive var e : semaphore ; e.initialize( 1 ) var f : semaphore ; f.initialize( 0 ) var buffer : string % invariant e.c+f.c < = 1 proc send( message : string ) e.acquire buffer := message % crit. sect. f.release ; end send proc receive( var message : string ) f.acquire message := buffer % crit. sect. e.release ; end receive end Messenger % module 11

  4. Concurrent programming slides T.S. Norvell (c) 2001 Note: the invariant is true at all times after initialization. According to the invariants, there are three states of the semaphores: • e.c=1 and f.c=0: The buffer is empty. send may be entered, but not receive • e.c=0 and f.c=1: The buffer is full. receive may be entered, but nor send • e.c=0 and f.c=0: Then some thread is executing a critical section. Other threads are locked out, of both send and receive , ensuring mutual exclusion on the critical sections. Buffer: sender attack at dawn drop off pick up write receiver pick up read drop off Buffer is full Buffer is empty 12

  5. Concurrent programming slides T.S. Norvell (c) 2001 Implementing semaphores Of course semaphores can be implemented using monitors, but monitors are not always available. We look at how to implement semaphores using process states. Each semaphore is represented by a record with two Þ elds: • s.count: int with abstraction relation: if s. count > = 0 then s.c = s. count else s.c = 0 • s.queue: a fair queue with invariant if s. count < 0 then s. queue . length = − s. count else s. queue . length = 0 Each operation is executed with mutual exclusion w.r.t. the others proc initialize( i : int ) ; pre i > = 0 count := i ; queue := theEmptyQueue end initialize 13

  6. Concurrent programming slides T.S. Norvell (c) 2001 In acquire, the thread loses mutual exclusion when it yields the CPU. proc acquire count -= 1 if count < 0 then put this thread on queue yield the CPU (enter the waiting state) end if end acquire proc release count += 1 if count < = 0 then remove a thread from queue and move that thread from waiting to the ready state end if end release Pro: • Multiple classes of critical sections. • No busy wait, and hence, good CPU utilization. 14

  7. Concurrent programming slides T.S. Norvell (c) 2001 Implementing Monitors Now we can Þ nally implement monitors. For each monitor m we need a semaphore m.s initialized to 1 • To enter m , execute m.s.acquire • To exit m , execute m.s.release For each condition variable c , declared within m , we need • an integer c.count initialized to 0. This counts the number of waiting threads. • a semaphore c.s , initialized to 0. wait c is implemented by c.count += 1 ; m.s.release ; c.s.acquire ; c.count -= 1 signal c is implemented by if c.count > 0 then c.s.release else m.s.release end if m.s.acquire empty(c) is implemented by c.count = 0 15

  8. Concurrent programming slides T.S. Norvell (c) 2001 Why this works When a thread acquires m.s it acquires an obligation to release m.s some time in the future. This obligation can be ful Þ lled either by exiting or by signalling. Signalling may pass the obligation to a thread waiting on c.s . Note: • c.count is protected by m.s • when a waiting thread is signaled, m.s.c remains 0 • c.s.acquire may be initiated before or after c.s.release . • Invariant: At all times m.s.c + P c ∈ C c.s.c ≤ 1 , where C is the set of all conditions declared in monitor m . • Think of a single pebble being taken from a bowl, held for a while, and then put into a bowl. 16

  9. Concurrent programming slides T.S. Norvell (c) 2001 Monitors vs. Semaphores Semaphores and monitors have equal expressive power since: each can be implemented by the other (see the ResourceMonitor ) So the question is: Which is easier to use and to reason about? Furthermore, the quality of the language was now the subject of objective scienti Þ c assessment, based on simplicity of the axioms and the guidance they give for program construction. The axiomatic method is a way to avoid the dogmatism and controversy that so often accompanies programming language design, particularly by committees. C.A.R. Hoare ‘Assertions: a personal perspective’ For mutual exclusion, monitors are more convenient as they pair-up acquisition of mutual exclusion with its release. For more complex coordination problems, monitors are easier to use since • Passing wait c indicates something is true right now — namely the condition • Passing s.acquire indicates something happened in the past — namely a release • Thus monitors allow the use of assertional reasoning whereas semaphores seem to require the use of operational reasoning.. 17

Recommend


More recommend