Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables...

108
Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: How do we make fair locks perform better? How do we notify threads of that some condition has been met? 1 Hale | CS450 Thanks to Remzi & Andrea Arapci-Dusseau for slide material

Transcript of Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables...

Page 1: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Concurrency:Signaling and Condition

VariablesQuestions Answered in this Lecture:• How do we make fair locks perform better?• How do we notify threads of that some condition has been met?

1Hale | CS450 Thanks to Remzi & Andrea Arapci-Dusseau for slide material

Page 2: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Recall: Ticket Lock Implementationtypedef struct __lock_t {

int ticket;

int turn;}

void lock_init(lock_t *lock) {

lock->ticket = 0;lock->turn = 0;

}

void acquire(lock_t *lock) {

int myturn = FAA(&lock->ticket);

while (lock->turn != myturn); // spin

}

void release (lock_t *lock) {

FAA(&lock->turn);

}

2Hale | CS450

Page 3: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Spinlock PerformanceFast when…- many CPUs- locks held a short time- advantage: avoid context switch

Slow when…- one CPU- locks held a long time- disadvantage: spinning is wasteful

3Hale | CS450

Page 4: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

spinspin spin spin spin

CPU Scheduler is Ignorant

A B

0 20 40 60 80 100 120 140 160

C D A B C D

lock unlock lock

CPU scheduler may run B instead of Aeven though B is waiting for A

4Hale | CS450

Page 5: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Ticket Lock with yield()typedef struct __lock_t {

int ticket;

int turn;}

void lock_init(lock_t *lock) {

lock->ticket = 0;lock->turn = 0;

}

void acquire(lock_t *lock) {

int myturn = FAA(&lock->ticket);

while (lock->turn != myturn)

yield();

}

void release (lock_t *lock) {

FAA(&lock->turn);

}

5Hale | CS450

Page 6: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

spinspin spin spin spin

A B

0 20 40 60 80 100 120 140 160

C D A B C D

lock unlock lock

A

0 20 40 60 80 100 120 140 160

A B

lock unlock lock

no yield:

yield:

yield() Instead of spin

6Hale | CS450

Page 7: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Spinlock PerformanceWaste…

Without yield: O(threads * time_slice)With yield: O(threads * context_switch)

So even with yield, spinning is slow with high thread contention

Next improvement: Block and put thread on waiting queue instead of spinning

7Hale | CS450

Page 8: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

How do we evaluate lock performance?

• Fairness: • do some processes wait more than others?• another way: do processes get lock in order requested?

• Performance: it depends…• Is the lock contended? (many threads attempting to acquire lock)• Or is it uncontended? (likely to get the lock if we request it)

Hale | CS450 8

Page 9: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

spinspin spin spin spin

A B

0 20 40 60 80 100 120 140 160

C D A B C D

lock unlock lock

A

0 20 40 60 80 100 120 140 160

A B

lock unlock lock

no yield:

yield:

Why is yield() useful?

9Hale | CS450

How can it affect performance?

Page 10: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Lock implementation: block when waiting

• Lock implementation removes waiting threads from the ready queue (e.g. with park() and unpark())• Scheduler only runs ready threads• Separates concerns (programmer doesn’t need to deal with yield vs

not/spinning issue)• Quiz: where should locks be implemented?

Hale | CS450 10

Page 11: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 11

0 2010 30 40 50 60 70 80 100

Ready: {A, B, C, D}

Waiting: {}Running: {}

Page 12: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 12

0 2010 30 40 50 60 70 80 100

Ready: {B, C, D}

Waiting: {}Running: {A}

A

lock()

Page 13: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 13

0 2010 30 40 50 60 70 80 100

Ready: {A, C, D}

Waiting: {}Running: {B}

A

lock()

B

Page 14: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 14

0 2010 30 40 50 60 70 80 100

Ready: {A, C, D}

Waiting: {B}Running: {}

A

lock()

B

lock()

Page 15: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 15

0 2010 30 40 50 60 70 80 100

Ready: {A, D}

Waiting: {B}Running: {C}

A

lock()

B

lock()

C

Page 16: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 16

0 2010 30 40 50 60 70 80 100

Ready: {A, C}

Waiting: {B}Running: {D}

A

lock()

B

lock()

C D

Page 17: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 17

0 2010 30 40 50 60 70 80 100

Ready: {A, C}

Waiting: {B, D}Running: {}

A

lock()

B

lock()

C D

lock()

Page 18: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 18

0 2010 30 40 50 60 70 80 100

Ready: {C}

Waiting: {B, D}Running: {A}

A

lock()

B

lock()

C D

lock()

A

Page 19: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 19

0 2010 30 40 50 60 70 80 100

Ready: {A}

Waiting: {B, D}Running: {C}

A

lock()

B

lock()

C D

lock()

A C

Page 20: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 20

0 2010 30 40 50 60 70 80 100

Ready: {C}

Waiting: {B, D}Running: {A}

A

lock()

B

lock()

C D

lock()

A C A

Page 21: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 21

0 2010 30 40 50 60 70 80 100

Ready: {C, B, D}

Waiting: {}Running: {A}

A

lock()

B

lock()

C D

lock()

A C A

unlock()

Page 22: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 22

0 2010 30 40 50 60 70 80 100

Ready: {C, B, D}

Waiting: {}Running: {A}

A

lock()

B

lock()

C D

lock()

A C A

unlock()

Page 23: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 23

0 2010 30 40 50 60 70 80 100

Ready: {B, D, A}

Waiting: {}Running: {C}

A

lock()

B

lock()

C D

lock()

A C A

unlock()

C

Page 24: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

Hale | CS450 24

0 2010 30 40 50 60 70 80 100

Ready: {D, A, C}

Waiting: {}Running: {B}

A

lock()

B

lock()

C D

lock()

A C A

unlock()

B

Page 25: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

What do we get?

• Threads aren’t contending on the lock when they shouldn’t be (mostly)• Fewer context switches

Hale | CS450 25

Page 26: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Lock: block when waiting

Hale | CS450 26

typedef struct {bool lock = false;bool guard = false;queue_t q;

} lock_t;

void acquire(lock_t *l) {while (TAS(&l->guard, true));if (l->lock) {

enqueue(l->q, tid);l->guard = false;park(); // blocked

} else {l->lock = true;l->guard = false;

}}

void release(lock_t *l) {while (TAS(&l->guard, true));if (qempty(l->q))

l->lock=false;else

unpark(dequeue(l->q));l->guard = false;

}

1. Why do we need guard?2. Why is it OK to spin on guard?3. In release(), why not set lock=false?4. What is the race condition?

Page 27: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Race!

Hale | CS450 27

void acquire(lock_t *l) {while (TAS(&l->guard, true));if (l->lock) {

enqueue(l->q, tid);l->guard = false;

park(); // blocked } else {

l->lock = true;l->guard = false;

}}

void release(lock_t *l) {while (TAS(&l->guard, true));if (qempty(l->q))

l->lock=false;else

unpark(dequeue(l->q));l->guard = false;

}

time

Thread 1 Thread 2

false!

bad!

Page 28: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Lock: the fix

Hale | CS450 28

typedef struct {bool lock = false;bool guard = false;queue_t q;

} lock_t;

void acquire(lock_t *l) {while (TAS(&l->guard, true));if (l->lock) {

enqueue(l->q, tid);setpark(); // notify of plan l->guard = false;park(); // unless unpark()

} else {l->lock = true;l->guard = false;

}}void release(lock_t *l) {

while (TAS(&l->guard, true));if (qempty(l->q))

l->lock=false;else

unpark(dequeue(l->q));l->guard = false;

}

1. Why does this fix the race?2. What does the scheduler need

to do here?3. Why can’t we just hold the

guard when we park()?

Page 29: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Spin-waiting vs. Blocking

• Each approach has tradeoffs:• Uniprocessor• Waiting process is scheduled -> process holding lock isn’t• Waiting process should always be descheduled• Associate queue of waiters with each lock

• Multiprocessor• Waiting process is scheduled -> process holding lock might also be• Spin or block depends on how long (𝒕) before lock is released• Lock released quickly? spin()• Lock taken for long time? block()

Hale | CS450 29

we’ll define this relative to thecontext switch time

Page 30: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Oracle

• Suppose we know how long (𝒕) a lock will be held• And suppose we make our decision to block or spin based on 𝑪, the

cost of a context switch

𝑎𝑐𝑡𝑖𝑜𝑛 = * 𝑡 ≤ 𝐶 → 𝑠𝑝𝑖𝑛𝑡 > 𝐶 → 𝑏𝑙𝑜𝑐𝑘

Hale | CS450 30

BUT: we have to know the future!

Page 31: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Applying Bounds

• The theory: bound our worst-case performance using actual wait time over optimal (oracle)• Consider:

Hale | CS450 31

𝑡 ≤ 𝐶What would the oracle do?

What can we do (without knowing future)?

𝑡 > 𝐶

What would the oracle do?

What can we do?

We pay 2C, because we wait an extra C. 2C/C = 2 => 2-competitive algorithm!

Page 32: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Concurrency Goals

• Mutual Exclusion• Keep two threads from executing in a critical section concurrently• We solved this with locks

• Dependent Events• We want a thread to wait until some particular event has occurred• Or some condition has been met• Solved with condition variables and semaphores

Hale | CS450 32

Page 33: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 33

“I just dropped in to see what condition my condition was in”

Page 34: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example: join()

pthread_t p1, p2;pthread_create(&p1, NULL, mythread, “A”);pthread_create(&p2, NULL, mythread, “B”);// join waits for the threads to finishpthread_join(p1, NULL);pthread_join(p2, NULL);printf(“Main: done\n [balance: %d]\n”, balance);return 0;

Hale | CS450 34

Page 35: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Condition Variables

• CV: queue of waiting threads• B waits for a signal on CV before running• wait(CV, …);

• A sends signal() on CV when time for B to run• signal(CV, …);

Hale | CS450 35

Page 36: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

API

• wait(cond_t * cv, mutex_t * lock)• assumes lock is held when wait() is called (why?)• puts caller to sleep + releases the lock (atomically)• when awoken, reacquires lock before returning

• signal(cond_t * cv)• wake a single waiting thread (if >= 1 thread is waiting)• if there is no waiting thread, NOP

Hale | CS450 36

Page 37: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #1

Hale | CS450 37

void thread_exit() {mutex_lock(&m); // acond_signal(&c); // bmutex_unlock(&m); // c

}

void thread_join() {mutex_lock(&m); // xcond_wait(&c, &m); // ymutex_unlock(&m); // z

}

parent child

Page 38: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #1

Hale | CS450 38

void thread_exit() {mutex_lock(&m); // acond_signal(&c); // bmutex_unlock(&m); // c

}

void thread_join() {mutex_lock(&m); // xcond_wait(&c, &m); // ymutex_unlock(&m); // z

}

parent child

Example schedule:parentchild

x ya b c

z

Page 39: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #1

Hale | CS450 39

void thread_exit() {mutex_lock(&m); // acond_signal(&c); // bmutex_unlock(&m); // c

}

void thread_join() {mutex_lock(&m); // xcond_wait(&c, &m); // ymutex_unlock(&m); // z

}

parent child

Example (bad) schedule:parentchild

x ya b c

parent will wait forever!

Page 40: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Rule of Thumb #1

• Always associate some state with the CV• CVs are used to signal() when state changes• If state is as required, don’t need to wait for a signal()

Hale | CS450 40

Page 41: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #2

Hale | CS450 41

void thread_exit() {done = 1 // acond_signal(&c); // b

}

void thread_join() {mutex_lock(&m); // wif (!done) // x

cond_wait(&c, &m);// ymutex_unlock(&m); // z

}

parent child

Page 42: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #2

Hale | CS450 42

void thread_exit() {done = 1 // acond_signal(&c); // b

}

void thread_join() {mutex_lock(&m); // wif (!done) // x

cond_wait(&c, &m);// ymutex_unlock(&m); // z

}

parent child

Example schedule:parentchild

w xa b

y z

fixed!

Page 43: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #2

Hale | CS450 43

void thread_exit() {done = 1 // acond_signal(&c); // b

}

void thread_join() {mutex_lock(&m); // wif (!done) // x

cond_wait(&c, &m);// ymutex_unlock(&m); // z

}

parent child

Example (bad) schedule:parentchild

w xa b

ysleeps forever!

Page 44: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #3 (correct)

Hale | CS450 44

void thread_exit() {mutex_lock(&m); // adone = 1 // bcond_signal(&c); // cmutex_unlock(&m);// d

}

void thread_join() {mutex_lock(&m); // wif (!done) // x

cond_wait(&c, &m);// ymutex_unlock(&m); // z

}

parent child

Page 45: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Join Implementation: Attempt #3 (correct)

Hale | CS450 45

void thread_exit() {mutex_lock(&m); // adone = 1 // bcond_signal(&c); // cmutex_unlock(&m);// d

}

void thread_join() {mutex_lock(&m); // wif (!done) // x

cond_wait(&c, &m);// ymutex_unlock(&m); // z

}

parent child

Example chedule:parentchild

w xa b

y

fixed!

c dz

Page 46: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 46

Bounded Buffer (producer-consumer queue)

Page 47: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 47

Bounded Buffer (producer-consumer queue)

t1: put()

Page 48: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 48

Bounded Buffer (producer-consumer queue)

t1: put()

Page 49: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 49

Bounded Buffer (producer-consumer queue)

t2: take()

Page 50: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 50

Bounded Buffer (producer-consumer queue)

t2: take()

Page 51: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 51

Bounded Buffer (producer-consumer queue)

Page 52: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 52

Bounded Buffer (producer-consumer queue)

t2: take()???

Page 53: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 53

Bounded Buffer (producer-consumer queue)

wait queue

t2

What condition are we waiting on?

Page 54: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 54

Bounded Buffer (producer-consumer queue)

wait queue

t2

t1: put()

Page 55: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 55

Bounded Buffer (producer-consumer queue)

wait queue

t2

t1: put()

What should happen?

Page 56: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 56

Bounded Buffer (producer-consumer queue)

wait queue

t2

t1: signal()

Page 57: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 57

Bounded Buffer (producer-consumer queue)

t2: take()

wait queue

Page 58: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Signaling between threads

Hale | CS450 58

Bounded Buffer (producer-consumer queue)

t2: take()

wait queue

Page 59: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 59

Bounded Buffer (producer-consumer queue)

Page 60: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 60

Bounded Buffer (producer-consumer queue)

most recent put

Page 61: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 61

Bounded Buffer (producer-consumer queue)

We’re full

Page 62: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 62

Bounded Buffer (producer-consumer queue)

t2:put()

wait queue

Page 63: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 63

Bounded Buffer (producer-consumer queue)wait queue

t2

Page 64: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 64

Bounded Buffer (producer-consumer queue)wait queue

t2

t1: take()

Page 65: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 65

Bounded Buffer (producer-consumer queue)wait queue

t2

Page 66: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 66

Bounded Buffer (producer-consumer queue)wait queue

t2

t1: signal()

Page 67: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 67

Bounded Buffer (producer-consumer queue)wait queue

t1: take()

Page 68: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 68

Bounded Buffer (producer-consumer queue)wait queue

t2:put()

Page 69: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 69

Bounded Buffer (producer-consumer queue)wait queue

t2:put()

Page 70: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

The queue is a circular queue

• Also sometimes called a ring buffer

Hale | CS450 70

Bounded Buffer (producer-consumer queue)wait queue

t2:put()wraparound property

Page 71: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Bounded Buffer

• Reads and writes to buffer require locking• when buffers are full, writers wait()• when buffers are empty, readers wait()• Many programming languages expose this abstraction directly• chan in Go• channel in Julia• Python requires a queue() with a lock()• Rust might use CircularBuffer() and CondVar() maybecrossbeam_channel()

Hale | CS450 71

Page 72: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Bounded Buffer

• Producers generate data• Consumers take data and process it• Very frequent situation encountered in systems programming• General strategy: use CVs to notify:• waiting readers when data is available• waiting writers when slots are free

Hale | CS450 72

Page 73: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Example

• Easy case: • 1 consumer thread• 1 producer thread• 1 shared buffer (max slots=1)

• numfill is buffer slots currently filled• let’s start with some code that doesn’t quite work

Hale | CS450 73

Page 74: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 74

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 75: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 75

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 76: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 76

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 77: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 77

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [SLEEPING]

numfull = 0

Page 78: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 78

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 79: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 79

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 80: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 80

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 81: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 81

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 82: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 82

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 1

Page 83: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 83

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 84: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 84

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 85: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 85

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 86: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 86

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 87: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 87

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 88: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 88

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[SLEEPING] [RUNNABLE]

numfull = 1

Page 89: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 89

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[SLEEPING] [RUNNING]

numfull = 1

Page 90: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 90

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[SLEEPING] [RUNNING]

numfull = 1

Page 91: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 91

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[SLEEPING] [RUNNING]

numfull = 1

Page 92: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 92

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[SLEEPING] [RUNNING]

numfull = 0

Page 93: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 93

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 94: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 94

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 95: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 95

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 96: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 96

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 97: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 97

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 98: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 98

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNABLE] [RUNNING]

numfull = 0

Page 99: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 99

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 100: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 100

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 101: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 101

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 0

Page 102: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 102

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [SLEEPING]

numfull = 1

Page 103: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 103

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m);while (numfull == max)

cond_wait(&cond, &m);do_fill(i);cond_signal(&cond);mutex_unlock(&m);

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m);while (numfull == 0)

cond_wait(&cond, &m);int tmp = do_get();cond_signal(&cond);mutex_unlock(&m);printf(“%d\n”, tmp);

}}

[RUNNING] [RUNNABLE]

numfull = 1

Page 104: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

What about two consumers?

• Can you find a bad schedule?

Hale | CS450 104

Page 105: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Hale | CS450 105

void *producer (void *arg) {for (int i = 0; i < loops; i++) {

mutex_lock(&m); // p1while (numfull == max) //p2

cond_wait(&cond, &m); //p3do_fill(i); // p4cond_signal(&cond); // p5mutex_unlock(&m); // p6

}}

void *consumer (void *arg) {while (1) {

mutex_lock(&m); // c1while (numfull == 0) // c2

cond_wait(&cond, &m);int tmp = do_get(); // c4cond_signal(&cond); // c5mutex_unlock(&m); // c6printf(“%d\n”, tmp); // c7

}}

[RUNNING] [RUNNABLE]

Producer:p1 p2 p3 p4 p5 p6 p1 p2 p3

Consumer1: c1 c2 c3

Consumer2: c1 c2 c3 c2 c4 c5

wait()wait()wait()

signal()signal()

does last signal wake producer or consumer1??

Page 106: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

How to wake the right thread?

• One solution:• wake all threads!

Hale | CS450 106

Page 107: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

API

• wait(cond_t * cv, mutex_t * lock)• assumes lock is held when wait() is called (why?)• puts caller to sleep + releases the lock (atomically)• when awoken, reacquires lock before returning

• signal(cond_t * cv)• wake a single waiting thread (if >= 1 thread is waiting)• if there is no waiting thread, NOP

• broadcast(cond_t * cv)• wake all waiters• if no waiting threads, NOP

Hale | CS450 107

Page 108: Concurrency: Signaling and Condition Variables · Concurrency: Signaling and Condition Variables Questions Answered in this Lecture: •How do we make fair locks perform better? •How

Summary

• Rules of thumb• Keep state in addition to CVs• Always wait() or signal() with lock held• Recheck state assumptions when waking up from waiting

Hale | CS450 108