130 likes | 328 Views
Some Concurrent Patterns. Producer/Consumer Avoid lock-step with bounded buffers Pipeline: chain of producer/consumer pairs Sleeping Barber: a producer/consumer rendezvous Dining Philosophers acquiring multiple locks Readers and Writers. Producer/Consumer via Semaphores.
E N D
Some Concurrent Patterns • Producer/Consumer • Avoid lock-step with bounded buffers • Pipeline: chain of producer/consumer pairs • Sleeping Barber: a producer/consumer rendezvous • Dining Philosophers • acquiring multiple locks • Readers and Writers
Producer/Consumer via Semaphores typeT buf; // a buffer of type Tsem empty = 1, full = 0; [Producer thread] { typeT prodData; while (true) { // produce prodData P(empty); buf = prodData; V(full); } } [Consumer thread] { typeT consData; while (true) { P(full); consData = buf; V(empty); // consume consData } }
Bounded Buffer typeT buf[n]; // n buffers of type Tsem empty = n, full = 0; int front = 0, rear = 0; [Producer thread] { typeT prodData; while (true) { // produce prodData P(empty); buf[rear] = prodData; rear = (rear + 1) % n; V(full); } } [Consumer thread] { typeT consData; while (true) { P(full); consData = buf[front]; front = (front + 1) % n; V(empty); // consume consData } }
Pipeline (Assembly Line) Input Thread A Thread B Thread C Output
Dining Philosophers • Typical failure: deadlock • Workaround: asymmetric lock acquisition • Alternate approach: allow only n-1 to eat at same time
The Wrong Solution sem fork[5] = {1, 1, 1, 1, 1};Philosopher thread[i = 0 to 4] { while(true) { P(fork[i]); P(fork[i+1]); eat; V(fork[i]); V(fork[i+1]); think; }}
Asymmetric Solution sem fork[5] = {1, 1, 1, 1, 1}; Philosopher thread[i = 0 to 3] { while(true) { P(fork[i]); P(fork[i+1]); eat; V(fork[i]); V(fork[i+1]); think; }} Philosopher thread[4] { while(true) { P(fork[0]); P(fork[4]); eat; V(fork[0]); V(fork[4]); think; }}
Readers/Writers • Writers need exclusive access • Readers can allow other readers in • Overly simple: don’t allow multiple readers • Better: designate first, last readers to handle the lock for the group • Problem: writers may get starved out • Solution: let writers keep “place in line”
Reader-Biased Solution sem rw = 1, mutexR = 1;int nr = 0; Reader thread[i = 1 to R] { while(true) { // other work here P(mutexR); nr = nr + 1; // if first reader if (nr == 1) P(rw); V(mutexR); do the reading; P(mutexR); nr = nr - 1; // if last reader if (nr == 0) V(rw); V(mutexR); }} Writer thread { while(true) { // other work here P(rw); do the writing; V(rw); }}
More Concurrent Patterns • Workgroup: single group vs organizations • Organization = layers of work groups • Client/Server • Same as workgroup, but client initiates • Typically less structured fan-out vs workgroup • Example: Web servers and thread pools • Scheduler/Requester • Resource-driven client/server (e.g. OS)
Work Group Input Thread A Thread B Thread C Output
Client/Server Client Request Client Request Client Request Server Client Handler Client Handler Client Handler
The Concurrency Trajectory Well Designed Concurrency - patterns - classic models - monitors Many implementations > Java > win32, .NET > C# Coordinated Concurrency - locks, semaphores - mutex, barriers One implementation > pthreads Concurrency - definitions - awareness of issues