synchronization-2 slides from: computer systems: a programmer's perspective, 2nd edition by...

40
SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011.

Upload: ashley-patrick

Post on 03-Jan-2016

218 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

SYNCHRONIZATION-2Slides from:

Computer Systems: A Programmer's Perspective, 2nd Edition

by Randal E. Bryant and David R. O'Hallaron, Pren-tice Hall, 2011.

Page 2: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Last Lecture

Sharing Synchronization

Page 3: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Critical Sections and Unsafe Regions

Def: A trajectory is safe iff it does not enter any unsafe region

Claim: A trajectory is correct (wrt cnt) iff it is safe

H1 L1 U1 S1 T1

H2

L2

U2

S2

T2

Thread 1

Thread 2

critical section wrt cnt

critical sec-tion wrt cnt

Unsafe region

unsafe

safe

Page 4: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Enforcing Mutual Exclusion

Question: How can we guarantee a safe trajectory?

Answer: We must synchronize the execution of the threads so that they never have an unsafe trajectory. i.e., need to guarantee mutually exclusive access to crit-

ical regions

Classic solution: Semaphores (Edsger Dijkstra)

Other approaches (out of our scope) Mutex and condition variables (Pthreads) Monitors (Java)

Page 5: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Semaphores

Semaphore: non-negative global integer synchronization variable

Manipulated by P and V operations: P(s): [ while (s == 0) wait(); s--; ]

Dutch for "Proberen" (test) V(s): [ s++; ]

Dutch for "Verhogen" (increment)

OS kernel guarantees that operations between brackets [ ] are executed indivisibly

Only one P or V operation at a time can modify s. When while loop in P terminates, only that P can decrement s

Semaphore invariant: (s >= 0)

Page 6: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

goodcnt.c: Proper Synchronization

Define and initialize a mutex for the shared variable cnt:

volatile int cnt = 0; /* Counter */ sem_t mutex; /* Semaphore that protects cnt */

Sem_init(&mutex, 0, 1); /* mutex = 1 */

Surround critical section with P and V:

for (i = 0; i < niters; i++) { P(&mutex); cnt++; V(&mutex); }

linux> ./goodcnt 10000OK cnt=20000linux> ./goodcnt 10000OK cnt=20000linux>

Warning: It’s much slower than badcnt.c.

Page 7: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Today

Producer-consumer problem Readers-writers problem Thread safety Races Deadlocks

Page 8: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Example: a producer-consumer problem

N buffers, counter (# of full buffers, 0 as initial value) Producer: produces a new buffer, increments counter Consumer: consumes a buffer, decrements counter

http://pages.cs.wisc.edu/~remzi/OSTEP/threads-cv.pdf

8

producerthread

sharedbuffer

consumerthread

Page 9: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Producer-Consumer Problem

Examples Multimedia processing:

Producer creates MPEG video frames, consumer renders them

Event-driven graphical user interfaces Producer detects mouse clicks, mouse movements, and

keyboard hits and inserts corresponding events in buffer Consumer retrieves events from buffer and paints the dis-

play

producerthread

sharedbuffer

consumerthread

Page 10: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Producer

while (true) { item * next_produced = produce();

// do nothing if buffers full

while (counter == BUFFER_SIZE) ;

buffer[in] = next_produced;

in = (in + 1) % BUFFER_SIZE;

counter++;

}

10

while (true) {

item* next_consumed;

// do nothing if no avail buff

while (counter == 0);

next_consumed = buffer[out];

out = (out + 1) % BUFFER_SIZE;

counter--;

consume(next_consumed);

}

Producer / Consumer

Consumer

Page 11: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Producer

while (true) { item * next_produced = produce();

// do nothing if buffers full

mutex_lock(&mutex);

while (counter == BUFFER_SIZE) {

mutex_unlock(&mutex);

process_yield(); // unlock and yield

mutex_lock (&mutex);

}

buffer[in] = next_produced;

in = (in + 1) % BUFFER_SIZE;

counter++;

mutex_unlock(&mutex);

}

11 while (true) {

item* next_consumed;

// do nothing if no avail buff

mutex_lock(&mutex);

while (counter == 0) {

mutex_unlock(&mutex);

process_yield();

mutex_lock (&mutex);

}

next_consumed = buffer[out];

out = (out + 1) % BUFFER_SIZE;

counter--;

mutex_unlock(&mutex);

consume(next_consumed);

}

Improved Producer / Consumer Consumer

Page 12: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Condition Variables

Problem: sometimes you want to wait until a condition happens.

E.g., wait for a child to finish (often called a join())

Page 13: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Condition variable

A condition variable is an explicit queue that threads can put themselves on when some state of execution (i.e., some condition) is not as desired.

That is you wait on the condition. Some other threads, when it changes the state can

then wake on (or more) of the waiting threads

Page 14: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Condition Variables Condition variables is a synchronization primitive that

helps us model events. A condition variable represents some condition that a

thread can: Wait on, until the condition occurs; or Notify other waiting threads that the condition has occur

It provides a place to wait (queue).

Page 15: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Condition Variables

Operations on condition variables: wait() -- Block until another thread calls signal() or broadcast() on the

CV signal() -- Wake up one thread waiting on the CV broadcast() -- Wake up all threads waiting on the CV

Pthread pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m); pthread_cond_signal(pthread_cond_t *c); pthread_cond_broadcast (pthread_cond_t *c);

Used with mutex

Page 16: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu-tex);

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

The pthread_cond_wait() and pthread_cond_timedwait() functions are used to block on a condition variable. They are called with mutex locked by the calling thread or undefined behaviour will result.

These functions atomically release mutex and cause the calling thread to block on the condition variable cond;

Page 17: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Broadcast

The pthread_cond_broadcast() function is used when-ever the shared-variable state has been changed in a way that more than one thread can proceed with its task.

Single producer/multiple consumer problem The producer would notify all consumers that might be wait-

ing; more throughput on a multi-processor. Read-write lock.

Wakes up all waiting readers when a writer releases its lock. Recommended readinghttp://pages.cs.wisc.edu/~remzi/OSFEP/threads-cv.pdf

Page 18: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

The pthread_cond_signal() call unblocks at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).

The pthread_cond_broadcast() call unblocks all threads currently blocked on the specified condition variable cond.

If more than one thread is blocked on a condition vari-able, the scheduling policy determines the order in which threads are unblocked.

Page 19: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011
Page 20: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011
Page 21: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011
Page 22: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Consume data

No data – wait()

C should have woken P!

Page 23: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Final version: Producer and consumer

Generalized to MAX items Important to use while statement to check the condition after wak-

ing up. It handles spurious wakeup.

cond_t empty, fill; mutex_t mutex;

void produce(int item) { pthread_mutex_lock(&mutex); while (count == MAX) pthread_cond_wait(&empty, &mutex); put(item); // put an item in the circular buffer pthread_cond_signal(&fill); // signal an item is filled ptherad_mutex_unlock(&mutex);}

int consumer() { pthread_mutex_lock(&mutex); while (count == 0) pthread_cond_wait(&fill, &mutex); int item = get(); pthread_cond_signal(&empty); pthread_mutex_unlock(&mutex); return item;}

Use two condition variables!

Page 24: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Barrier Synchronization

A wait at a barrier causes a thread to wait until all threads have performed a wait at the barrier.

At that point, they all proceed.

Page 25: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Implementing Barriers in Pthreads

Count the number of arrivals at the barrier. Wait if this is not the last arrival. Make everyone unblock if this is the last arrival. Since the arrival count is a shared variable, enclose the

whole operation in a mutex lock-unlock.

Page 26: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Implementing Barriers in Pthreads

void barrier(){

pthread_mutex_lock(&mutex_arr);arrived++;if (arrived<N) {

pthread_cond_wait(&cond, &mutex_arr);}else {

pthread_cond_broadcast(&cond); arrived=0; /* be prepared for next barrier */ }

pthread_mutex_unlock(&mutex_arr);}

Page 27: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Case Study: Prethreaded Concurrent Server

Masterthread Buffer ...

Acceptconnections

Insertdescriptors Remove

descriptors

Workerthread

Workerthread

Client

Client

...

Service client

Service client

Pool of worker

threads

Page 28: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Today

Producer-consumer problem Readers-writers problem Thread safety Races Deadlocks

Page 29: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Readers-Writers Problem

Generalization of the mutual exclusion problem

Problem statement: Reader threads only read the object Writer threads modify the object Writers must have exclusive access to the object Unlimited number of readers can access the object

Occurs frequently in real systems, e.g., Online airline reservation system Multithreaded caching Web proxy

Page 30: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Solution to First Readers-Writers Problem using mutex

int readcnt; /* Initially 0 */sem_t mutex, w; /* Both initially 1 */

void reader(void) { while (1) { P(&mutex); readcnt++; if (readcnt == 1) /* First in */ P(&w); V(&mutex);

/* Reading happens here */

P(&mutex); readcnt--; if (readcnt == 0) /* Last out */ V(&w); V(&mutex); }}

void writer(void) { while (1) { P(&w);

/* Writing here */

V(&w); }}

Readers:

Writers rw1.c

Page 31: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Pthread provides read/write lock

pthread_rwlock_init()

pthread_rwlock_rdlock() pthread_rwlock_wrlock()

Reader Writer

Reader OK No

Writer No No

Access permission table

Page 32: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Today

Producer-consumer problem Readers-writers problem Thread safety Races Deadlocks

Page 33: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Crucial concept: Thread Safety

Functions called from a thread must be thread-safe

Def: A function is thread-safe iff it will always produce correct results when called repeatedly from multiple concurrent threads.

Classes of thread-unsafe functions: Class 1: Functions that do not protect shared variables. Class 2: Functions that keep state across multiple invocations. Class 3: Functions that return a pointer to a static variable. Class 4: Functions that call thread-unsafe functions.

Page 34: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Unsafe Functions (Class 1)

Failing to protect shared variables Fix: Use P and V semaphore operations Example: goodcnt.c Issue: Synchronization operations will slow down code

Page 35: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Unsafe Functions (Class 2)

Relying on persistent state across multiple function invocations Example: Random number generator that relies on

static state static unsigned int next = 1;

/* rand: return pseudo-random integer on 0..32767 */ int rand(void) { next = next*1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } /* srand: set seed for rand() */ void srand(unsigned int seed) { next = seed; }

Page 36: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Safe Random Number Generator

Pass state as part of argument and, thereby, eliminate static state

Consequence: programmer using rand_r must main-tain seed

/* rand_r - return pseudo-random integer on 0..32767 */ int rand_r(int *nextp) { *nextp = *nextp*1103515245 + 12345; return (unsigned int)(*nextp/65536) % 32768; }

Page 37: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Unsafe Functions (Class 3)

Returning a pointer to a static vari-able

Fix 1. Rewrite function so caller passes address of variable to store result Requires changes in caller and callee

Fix 2. Lock-and-copy Requires simple changes in caller (and

none in callee) However, caller must free memory.

/* lock-and-copy version */char *ctime_ts(const time_t *timep, char *privatep){ char *sharedp;

P(&mutex); sharedp = ctime(timep); strcpy(privatep, sharedp); V(&mutex); return privatep;}

Warning: Some functions like gethost-byname require a deep copy. Use reen-trant gethostbyname_r version instead.

Page 38: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Unsafe Functions (Class 4)

Calling thread-unsafe functions Calling one thread-unsafe function makes the en-

tire function that calls it thread-unsafe

Fix: Modify the function so it calls only thread-safe functions

Page 39: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Reentrant Functions

Def: A function is reentrant iff it accesses no shared vari-ables when called by multiple threads. Important subset of thread-safe functions.

Require no synchronization operations. Only way to make a Class 2 function thread-safe is to make it reen-

trant (e.g., rand_r ) Reentrant function has a property that it can be interrupted in the

middle of its execution and then safely called again.

Reentrantfunctions

All functions

Thread-unsafefunctions

Thread-safefunctions

Page 40: SYNCHRONIZATION-2 Slides from: Computer Systems: A Programmer's Perspective, 2nd Edition by Randal E. Bryant and David R. O'Hallaron, Prentice Hall, 2011

Thread-Safe Library Functions

All functions in the Standard C Library (at the back of your K&R text) are thread-safe Examples: malloc, free, printf, scanf

Most Unix system calls are thread-safe, with a few ex-ceptions:Thread-unsafe function Class Reentrant version

asctime 3 asctime_rctime 3 ctime_rgethostbyaddr 3 gethostbyaddr_rgethostbyname 3 gethostbyname_rinet_ntoa 3 (none)localtime 3 localtime_rrand 2 rand_r