Classic Synchronization Problems and Deadlock

Classic Synchronization Problems and Deadlock

Value Queue “acquire” op “release” op “broadcast” or “release all” op Lock 0/1 ? Lock Unlock No Block till value = 0; Value = 0 set value = 1 8: Classic Synchronization Semaphore INT Y Wait Signal No? value — Value++ While (getValue()<0){ Problems and Deadlock If value < 0 If value <=0 Signal Add self to queue Wake up one } Condition N/A Y Wait Signal Easy to variable Put self on queue If process on Support Last Modified: queue, wake up A signal all 6/14/2004 11:54:49 AM one Event 0/1 Y Wait Signal Default signal does If Value = 0, put Value = 1 self on queue Wake up all Monitor 0/1 Y Call proc in monitor Return from proc No in monitor -1 -2 Bounded Buffer Classical Synchronization Problems Producer/Consumer r Bounded-Buffer Problem r Finite size buffer (array) in memory shared by (also called Producer-Consumer) multiple processes/threads r Producer threads “produce” an item and place in in the buffer r Readers and Writers Problem r Consumer threads remove an item from the buffer and “consume” it r Why do we need synchronization? r Dining-Philosophers Problem m Shared data = the buffer state m Which parts of buffer are free? Which filled? r What can go wrong? m Producer doesn’t stop when no free spaces; Consumer tries to consume an empty space; Consumer tries to consume a space that is only half-filled by the producer; Two producers try to produce into same space; Two -3 consumers try to consume the same space,… -4 Monitor Solution to Bounded- Monitor Solution to Bounded- Buffer Buffer container_t { //monitor boundedBuffer cont void consumer (){ BOOL free = TRUE; while( allBuffersEmpty()){ void producer (){ item_t item; wait(notAllEmpty) while( allBuffersFull()){ } } wait(notAllFull ) monitor boundedBuffer { } which = findFullBuffer (); conditionVariable notAllFull; consumeItem(which->item); conditionVariable notAllEmpty; which = findFreeBuffer (); which->free = TRUE; container_t buffer[FIXED_SIZE]; which->free = FALSE; numFull--; int numFull = 0; which->item = produceItem(); numFull++ signal(notAllFull); } signal(notAllEmpty ); } } //end Monitor -5 -6 1 Semaphore Solution to Semaphore Solution to Bounded-Buffer Bounded-Buffer semaphore_t mutex; void producer (){ void consumer (){ semaphore_t full; container_t *which; container_t *which; semaphore_t empty; wait(empty); wait(full); wait ( mutex); wait ( mutex); container_t { BOOL free = TRUE; which = findFreeBuffer (); item_t item; which = findFullBuffer (); which->free = FALSE; } consumeItem(which->item); container_t which->item = produceItem(); which->free = TRUE; buffer[FIXED_SIZE]; signal (mutex); signal (mutex); void initBoundedBuffer { signal (full); signal (empty); mutex.value = 1; } } full.value = 0; empty.value = FIXED_SIZE •Can we do better? Lock held while produce/consume? } -7 -8 Semaphore Solution to Readers/ Readers/writers Writers (Reader Preference) semaphore_t mutex; r Shared data area being accessed by multiple void reader (){ semaphore_t okToWrite; processes/threads int numReaders ; wait(mutex ); numReaders ++; r Reader threads look but don’t touch void init{ if (numReaders ==1) m We can allow multiple readers at a time. Why? mutex.value = 1; wait(okToWrite); //not ok to write r Writer threads touch too. okToWrite.value = 1; signal(mutex); numReaders = 0; m If a writer present, no other writers and no readers. } do reading (could pass in pointer to Why? void writer (){ read function) wait( okToWrite); r Is Producer/Consumer a subset of this? do writing (could pass wait(mutex ); m Producers and consumers are both writers in pointer to write function) numReaders --; m Producer = writer type A; Consumer = writer type B and if (numReaders == 0) no readers signal(okToWrite); signal(okToWrite ); //ok to write again } m What might be a reader? Report current num full. signal (mutex); Can we do better? Fairness? -9 } -10 Monitor solution to Semaphore Solution to Readers/ This one favors writers; readers/writers How? Can readers starve? Writers (Fair) Monitor readersWriters { void startWrite() { semaphore_t readCountMutex, incoming, next; int numReaders = 0; BOOL writeInProgress = while (numReaders || int numReaders; writeInProgress){ FALSE; BOOL writeInProgress, readInProgress; int okToWriteQueued = 0; okToWriteQueued++; conditionVariable okToWrite; wait( okToWrite); void init{ conditionVariable okToRead; okToWriteQueued-- ; } readCountMutex.value = 1; void startRead () { writeInProgress = TRUE; incoming.value = 1; while (writeInProgress || } okToWriteQueued){ next.value = 1; wait (okToRead); void finishWrite(){ numReaders = 0; } writeInProgress = FALSE; writeInProgress = FALSE; numReaders ++; if ( okToWriteQueued){ signal( okToRead ); signal( okToWrite); readInProgress = FALSE; } } else { } signal(okToRead); void finishRead(){ } numReaders--; if (numReaders == 0){ } signal( okToWrite); } //end monitor -11 -12 } 2 Semaphore Solution to Readers/ Remember void reader (){ Writers (Fair) wait(incoming); void writer (){ if (!readInProgress) { wait (incoming); wait (next); r Game is obtaining highest possible degree of wait(next); } concurrency and greatest ease of programming wait(readCountMutex); writeInProgress = TRUE; numReaders++; r Tension readInProgress = TRUE; signal(readCountMutex); m Simple and high granularity locks easy to program //Let someone else move on //to wait on next m Simple and high granularity locks often means low //If next on incoming is signal(incoming); //writer will block on next concurrency //If reader will come in signal(incoming); do writing r Getting more concurrency means do reading m Finer granularity locks, more locks writeInProgress = FALSE; m if (next.value == 0){ wait(readCountMutex); More complicated rules for concurrent access numReaders--; signal (next); if (numReaders == 0){ } readInProgress = FALSE; } if (next.value == 0){ signal (next); } } signal(readCountMutex); -13 -14 Semaphore Solution to Dining Dining-Philosophers Problem Philosophers Problem? //array of chopsticks, chopstick i is philosopher 0 gets chopstick 0 to the right of philosopher i philosopher 1 gets chopstick 1 void philosophersLife(int i){ …. semaphore_t while (1) { int rightChopstick, leftChopstick; philosopher N gets chopstick N chopstick[NUM_PHILOSOPHERS]; think(); //figure out which chopsticks I need Deadlock! Solution? rightChopstick = i; void init(){ leftChopstick = i -1+ NUM_PHILOSOPHERS % NUM_PHILOSOPERS; //grab chopsticks for (i=0; i< NUM_PHILOSOPHERS; i++) wait(chopstick[rightChopstick]) wait(chopstick[leftChopstick ]); chopstick[i].value = 1; eat(); } //putdown chopsticks signal(chopstick[ rightChopstick]) signal(chopstick[ leftChopstick]); } } -15 -16 Deadlock Fixing Dining Philosophers r Deadlock exists in a set of r Make philosophers grab both chopsticks processes/threads when all they need atomically processes/threads in the set are waiting m Maybe pass around a token (lock) saying who for an event that can only be caused by can grab chopsticks another process in the set (which is also m Get a global lock before can lock any chopsticks waiting!). r Make a philosopher give up a chopstick r Dining Philosophers is a perfect example. r Others? Each holds one chopstick and will wait forever for the other. -17 -18 3 Cycle in Resource Allocation Resource Allocation Graph Graph Philosopher 1 has chopstick 1 and wants chopstick 0 r Deadlock can be described through a resource allocation graph Chopstick 0 Philosopher 1 Chopstick 1 r Each node in graph represents a Philosopher process/thread or a resource Cycle: P0, C3, P3, C2, P2, 2 has chopstick 2 Philosopher 0 C1, P1, C0, P0 Philosopher 2 r An edge from node P to R indicates that and wants process P had requested resource R chopstick 1 r An edge from node R to node P indicates Chopstick 3 Chopstick 2 that process P holds resource R Philosopher 0 has Philosopher 3 r If graph has cycle, deadlock may exist. If chopstick 0 and wants Philosopher 3 has chopstick 3 chopstick 3 graph has no cycle, deadlock cannot exist. and wants chopstick 2 wait(chopstick[i]) wait(chopstick[(i-1) % NUM_PHILOSOPHERS]) -19 -20 Better Semaphore Solution to No Cycle in Resource Allocation Dining Philosophers Graph Chopstick 0 Philosopher 1 Chopstick 1 void philosophersLife(int i){ Always wait for low chopstick first No cycle! while (1) { No deadlock! think(); Why better? if ( rightChopstick < leftChopstick}{ This is not the Philosopher 2 Philosopher 0 wait(chopstick[rightChopstick ]); One philosopher only possible wait(chopstick[leftChopstick]); reaches right first when outcome. P1 } else { all others reach left could get wait(chopstick[leftChopstick]); chopstick 0 Chopstick 3 wait(chopstick[rightChopstick ]); Two philsophers reach first, similarly Chopstick 2 } for same one and one will P3 could get Philosopher 3 lose; The one who wins chopstick 3 eat(); will get both chopsticks first. and finish – allowing Regardless, if ( rightChopstick < leftChopstick}{ signal( rightChopstick); everyone to finish someone will wait(chopstick[rightChopstick ]); signal( leftChopstick); eventually get both their wait(chopstick[leftChopstick]); chopsticks and } else { } No circular wait! No be able to wait(chopstick[leftChopstick]); wait(chopstick[rightChopstick ]); } deadlock!! finish -21 } -22 Conditions for Deadlock Deadlock Prevention r Deadlock can exist only if the following four r Four necessary and sufficient conditions conditions are met; for deadlock m Mutual Exclusion – some resource must be held m Mutual Exclusion exclusively m Hold and Wait m Hold and Wait – some process must be holding one resource and waiting for another m No

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    9 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us