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?
53
Embed
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.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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
Time Is count still 5? 4, 6?Is count still 5? 4, 6?
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?Is count still 5? 4, 6?Time
Critical-Section Management
Critical section: the part of the program where shared variables are accessed
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
1.Locks
2.Semaphore
3.Conditional Variables
Solution to Critical-section Problem
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.
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.
}
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.
Example
Lock *k= new Lock (“Lock”);
k->Acquire();
Perform critical section operations.
k->Release();
}
Synchronization with Locks: Example
int a=0;Lock *k;void sum (int p){ int c; k->Acquire();
• 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++; }
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.
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
}
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);
}
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
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
Synchronization AttemptConsumer loop:
while (count == 0) ;
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
Use dataProducer loop:
Produce next item
while (count == BUFFER_SIZE) ;
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
out
incount
Deadlock?How to avoid spin?
Another Synchronization AttemptConsumer loop:
while (count == 0) ;
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
Use dataProducer loop:
Produce next item
while (count == BUFFER_SIZE) ;
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
out
incount
Mutual execution?
in
What can happen with this trace?
Consumer 1 :
while (count == 0) ;
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
Do other things
out
incount
in
Consumer 2:
while (count == 0) ;
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
Use data and do others
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
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
Semaphore for consumer/producer problem with bounded buffer
What condition to check for bounded buffer?
Conditions to check: Is there a data item available to consume? Is there space available to produce a data
item? Wait using two semaphores
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.
Producer thread:
while(1){
produce next item;
data->V(); //notify item is available
}
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.
Synchronization with semaphore/lock?Consumer loop:
data->P();
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
space->V();
Use dataProducer 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
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
Synchronization with semaphore/lock?Consumer loop:
data->P();
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
space->V();
Use dataProducer 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?
Solution to Critical-section Problem
1.Locks
2.Semaphore
3.Conditional Variables
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.
}
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 availableL.Release();Do other things
Can conditionstill be true afterwake-up?How to protect?
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 availableL.Release();Do other things
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
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.
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
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
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);
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, &