Presentation is loading. Please wait.

Presentation is loading. Please wait.

Class Announcement TA is expected to add/move office hours to tomorrow for Project 0 Project 0 deadline is extended to next Monday April 13 noon. A copy.

Similar presentations


Presentation on theme: "Class Announcement TA is expected to add/move office hours to tomorrow for Project 0 Project 0 deadline is extended to next Monday April 13 noon. A copy."— Presentation transcript:

1 Class Announcement TA is expected to add/move office hours to tomorrow for Project 0 Project 0 deadline is extended to next Monday April 13 noon. A copy of the text book reserved in the library. Any Issues for Project 0?  Pass all public tests locally and then fail in submit.cs?

2 Testfile2 without/with an invalid command ls -l > temp wc temp ls -l -f > temp wc temp2 sort temp3 cat temp2 diff temp2 temp3 > temp4 wc temp4 exit ls -l > temp wc temp ls -l -f > temp wc temp2 sort temp3 catt temp2 diff temp2 temp3 > temp4 wc temp4 exit

3 Testfile4 without/with an invalid command ls -l -f | sort > temp ls -l | sort > temp1 diff temp temp1 > temp2 cat temp3 diff temp3 temp |sort | wc > temp4 cat temp4 exit ls -l -f | sort > temp ls -l | sort > temp1 diff temp temp1 > temp2 cat temp3 catt temp3 | wc diff temp3 temp |sort | wc > temp4 cat temp4 exit Autograding only compares with expected answers for processing all valid commands. Donot test weird cases.

4 Lecture 5: Process/Thread Synchronization CS170. UCSB. 2015. T. Yang

5 Topics The critical-section problem and examples Solutions  Locks  Semaphores  Condition variables (monitors). Synchronization in Nachos and Pthreads

6 Application example that needs synchronization 2 producer threads and 2 consumer threads Shared data

7 Shared variables in a producer/consumer program  count -- number of items available  in -- points to the writeable slot  out -- points to the slot to read in out

8 Producer Thread Code while (true) { while (count == BUFFER_SIZE) ; // buffer is full, spin buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; } in

9 Consumer thread while (true) { while (count == 0) ; // Nothing is available. Spin nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; } out

10 Race Conditions: Example Count--; Producer thread Consumer thread Count++; Count=5 Is count still 5? Race Conditions: two or more processes (threads) are reading and writing on shared data and the final result depends on who runs precisely & when

11 Review compiled code Count—: register2 = count register2 = register2 - 1 count = register2 Producer thread Consumer thread Count++: register1 = count register1 = register1 + 1 count = register1 Count=5 Is count still 5?

12 Executing compiled code Count—: register2 = count register2 = register2 - 1 count = register2 Producer thread Consumer thread Count++: register1 = count register1 = register1 + 1 count=register1 Count=5 Time Is count still 5? 4, 6?

13 Executing compiled code Count—: register2 = count register2 = register2 - 1 count = register2 Producer thread Consumer thread Count++: register1 = count register1 = register1 + 1 count = register1 Count=5 Is count still 5? 4, 6? Time

14 Critical-Section Management Critical section: the part of the program where shared variables are accessed

15 Property of Critical-Section Solutions 1.Mutual Exclusion – Only one can enter the critical section. Safety property in AD book 2.Progress - If some processes wish to enter their critical section and nobody is in the critical section, then one of them will enter in a limited time. Liveness property in AD book 3.Bounded Waiting - If one process starts to wait for entering an critical section, there is a limit on the number of times other processes entering the section before this process enters. Liveness property in AD book

16 1. Locks 2. Semaphore 3. Conditional Variables Solution to Critical-section Problem

17 Acquire lock Critical section Release lock Lock for Critical-section Problem Thread waits if there is a lock. It enters the critical after acquiring a lock. Only the thread who locks can unlock.

18 Nachos Lock Interface Lock can be in one of two states: locked or unlocked class Lock { public: Lock (char *name); //create a lock with unlocked state ~Lock(); void Acquire(); //Atomically waits until the lock is unlocked, and then sets the lock to be locked. void Release(); //Atomically changes the state to be unlocked. Only the thread who owns the lock can release. }

19 How to use locks Typically associate a lock with a piece of shared data for mutual execlusion. When a thread needs to access, it first acquires the lock, and then accesses data. Once access completes, it releases the lock. l Example Lock *k= new Lock (“Lock”); k->Acquire(); Perform critical section operations. k->Release(); }

20 Synchronization with Locks: Example int a=0; Lock *k; void sum (int p){ int c; k->Acquire(); a=a+1; c=a; k->Release() printf(“%d : a= %d\n”, p,c); } void main() { Thread *t=new Thread (“Child”); k=new Lock(“Lock”); t->Fork(sum,1); sum(0); }

21 Semaphore for the critical-section problem Semaphore S – nonnegative integer variable Can only be accessed /modified via two indivisible (atomic) operations  wait (S) { //also called P() while S <= 0 ; // wait in a queue S--; }  signal (S) { //also called V() //wake up some waiting thread S++; }

22 Semaphore Counting semaphore – initial value representing how many threads can be in the critical section.  Binary semaphore (also known as mutex locks) – integer value ranged between 0 and 1. Provides mutual exclusion Semaphore mutex; // initialized to 1 do { P(mutex); // Critical Section V(mutex); } while (TRUE); Not recommended by the AD text book (Chapter 5.8), but still widely used.

23 Semaphores in Nachos class Semaphore{ public: Semaphore (char *name, int counter); // initial counter value ~Semaphore(); void P(); //Atomically waits until the counter is greater than 0 and then decreases the counter void V(); //Atomically increases the counter }

24 Synchronization with Semaphore: Example int a=0; Semaphore *s; void sum (int p){ int c; s->P(); a=a+1; c=a; s->V(); printf(“%d : a= %d\n”, p,c); } void main() { Thread *t=new Thread (“Child”); s=new Semaphore(“S”,1); t->Fork(sum,1); sum(0); }

25 Synchronization in Consumer thread while (true) { while (count == 0) ; // sping waiting nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data for other things } out

26 Synchronization in Producer/ Consumer threads Consumer loop: while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data and do others Producer loop: Produce next item while (count == BUFFER_SIZE) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; out What is shared? How to synchronize? count in

27 Synchronization Attempt Consumer loop: while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data Producer loop: Produce next item while (count == BUFFER_SIZE) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; out in count Deadlock? How to avoid spin?

28 Another Synchronization Attempt Consumer loop: while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data Producer loop: Produce next item while (count == BUFFER_SIZE) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; out in count Mutual execution? in

29 What can happen with this trace? Consumer 1 : while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Do other things out in count in Consumer 2: while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data and do others

30 Semaphore for consumer/producer problem Simplify the problem:  Unbounded buffer  Worry about bounded buffer constraint later Condition to check:  Is there a data item available to consume?  Not available?  Wait using 1 semaphore

31 Semaphore for consumer-producer problem with unbounded buffer  Semaphore *data =new Semaphore(“Data”, 0); –Indicate # of data items available for consuming  Consumer thread: while(1) { data-> P(); //wait until an item is available Use data item; }  Producer thread: while(1){ produce next item; data->V(); //notify an item is available } Semaphore can do more than mutual exclusion, and can synchronize a consumer/producer pipe

32 Semaphore for consumer/producer problem with bounded buffer n What condition to check for bounded buffer? Conditions to check: l Is there a data item available to consume? l Is there space available to produce a data item? l Wait using two semaphores

33 Consumer-producer problem with bounded buffer Two semaphores:  Semaphore *data =new Semaphore(“Data”, 0); –Indicate # of data items available for consuming  Semaphore *space =new Semaphore(“Space”, 10);  Indicate # of 10 data slots available. l Producer thread: while(1){ produce next item; data->V(); //notify item is available }

34 Consumer-producer problem with bounded buffer Two semaphores:  Semaphore *data =new Semaphore(“Data”, 0); –Indicate # of data items available for consuming  Semaphore *space =new Semaphore(“Space”, 10);  Indicate # of 10 data slots available. l Producer thread: while(1){ space->P();//wait until space is available produce next item; data->V(); //notify data is available }

35 Consumer-producer problem with bounded buffer  Semaphore *data =new Semaphore(“Data”, 0);  Semaphore *space =new Semaphore(“Space”, 10); l Producer thread: while(1){ space->P();//wait until space is available produce next item; data->V(); //notify data is available } l Consumer thread: while(1){ data->P();//wait until data is available consume next item; }

36 Consumer-producer problem with bounded buffer  Semaphore *data =new Semaphore(“Data”, 0);  Semaphore *space =new Semaphore(“Space”, 10); l Producer thread: while(1){ space->P();//wait until space is available produce next item; data->V(); //notify data is available } l Consumer thread: while(1){ data->P();//wait until data is available consume next item; space->V();//notify space is available }

37 Synchronization for pthreads: Mutex pthread_mutex_t mutex; const pthread_mutexattr_t attr; int status; status = pthread_mutex_init(&mutex,&attr); status = pthread_mutex_destroy(&mutex); status = pthread_mutex_unlock(&mutex); status = pthread_mutex_lock(&mutex); - block Thread i …… lock(mutex) …… critical region …… unlock(mutex ) ……

38 Semaphore for Pthreads int status,pshared; sem_t sem; unsigned int initial_value; status = sem_init(&sem,pshared,initial_value); status = sem_destroy(&sem); status = sem_post(&sem); status = sem_wait(&sem);

39 What now? Consumer loop: while (count == 0) ; nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; Use data Producer loop: Produce next item while (count == BUFFER_SIZE) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; out in count How to use semaphore with lock?

40 Synchronization with semaphore Consumer loop: data->P(); nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; space->V(); Use data Producer loop: Produce next item space->P();//wait until space is available) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; data->V(); //notify data is available

41 Synchronization with semaphore/lock? Consumer loop: data->P(); nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; space->V(); Use data Producer loop: Produce next item space->P();//wait until space is available) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; data->V(); //notify data is available

42 What happens when a consumer does not hod a lock after waking up from data->p()? Consumer 1: data->P(); nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; space->V(); Use data Consumer 2: data->P(); nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; space->V(); Use data

43 Synchronization with semaphore/lock? Consumer loop: data->P(); nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; space->V(); Use data Producer loop: Produce next item space->P();//wait until space is available) ; buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; data->V(); //notify data is available How to hold a lock immediately after waking up?

44 Solution to Critical-section Problem 1. Locks 2. Semaphore 3. Conditional Variables

45 Condition Variables in Nachos Pair it with a lock class Condition { public: Condition(char *name); ~Condition(); void Wait(Lock *mylock); //Atomically releases the lock and waits. When it is returned, the lock is reacquired again. void Signal(Lock *myLock); //Wake up one waiting thread to run. The lock is not released. void Broadcast(Lock *myLock); //Wake up all threads waiting on the condition. The lock is not released. }

46 Condition Variables for consumer- producer problem with unbounded buffer int avail=0; // # of data items available for consumption Lock *L; Condition *cv= new Condition (“condition”); Consumer thread loop: L.Acquire(); if (avail <=0) cv.Wait(L); Fetch next item; avail = avail-1; L.Release(); Do other things  Producer thread loop: L.Acquire(); Add next item; avail = avail+1; cv.Signal(L); //notify an item is available L.Release(); Do other things Can condition still be true after wake-up? How to protect?

47 Condition Variables for consumer- producer problem with unbounded buffer int avail=0; // # of data items available for consumption Lock *L; Condition *cv= new Condition (“condition”); Consumer thread loop: L.Acquire(); while(avail <=0) cv.Wait(L); Fetch next item; avail = avail-1; L.Release(); Do other things  Producer thread loop: L.Acquire(); Add next item; avail = avail+1; cv.Signal(L); //notify an item is available L.Release(); Do other things

48  Thread 1 mylock.Acquire(); When condition is not satisfied, cv.Wait(mylock); Critical Section; mylock.Release();  Thread 2: mylock.Acquire(); When condition can satisfy, cv.Signal(mylock); mylock.Relase(); How to Use Condition Variables: Typical Flow

49 When to use condition broadcast()? When waking up one thread to run is not sufficient. Example: concurrent malloc()/free() for allocation and deallocation of objects with non- uniform sizes.

50 malloc()/free() with condition broadcast Initially 10 bytes are free. m() stands for malloc(). f() for free() Thread 1: m(10) – succ f(10) –broadcast? m(7) – wait Resume m(7)-wait Thread 2: m(5) – wait Resume m(5)-succ f(5) –broadcast? Thread 3: m(5) – wait Resume m(5)-succ m(3) –wait Resume m(3)-succ

51 malloc()/free() with condition signal Initially 10 bytes are free. m() stands for malloc(). f() for free() Thread 1: m(10) – succ f(10) –signal? m(7) – wait Resume m(7)-wait Thread 2: m(5) – wait Resume m(5)-succ f(5) –signal? Thread 3: m(5) – wait Resume m(5)-succ m(3) –wait Resume m(3)-succ

52 Pthread synchronization: Condition variables int status; pthread_condition_t cond; const pthread_condattr_t attr; pthread_mutex mutex; status = pthread_cond_init(&cond,&attr); status = pthread_cond_destroy(&cond); status = pthread_cond_wait(&cond,&mutex); status = pthread_cond_signal(&cond); status = pthread_cond_broadcast(&cond);

53 Summary Concurrent threads are a very useful abstraction  Allow transparent overlapping of computation and I/O  Allow use of parallel processing when available Concurrent threads introduce problems when accessing shared data  Programs must be insensitive to arbitrary interleaving  Without careful design, shared variables can become completely inconsistent Synchronization with lock, condition variables, & semaphores


Download ppt "Class Announcement TA is expected to add/move office hours to tomorrow for Project 0 Project 0 deadline is extended to next Monday April 13 noon. A copy."

Similar presentations


Ads by Google