+ All Categories
Home > Documents > Concurrency, Races, &...

Concurrency, Races, &...

Date post: 18-Jan-2021
Category:
Upload: others
View: 8 times
Download: 0 times
Share this document with a friend
177
Science Computer Science Concurrency, Races, & Synchronization CS 450: Operating Systems Sean Wallace <[email protected]>
Transcript
Page 1: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

ScienceComputer Science

Concurrency, Races, & Synchronization

CS 450: Operating SystemsSean Wallace <[email protected]>

Page 2: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Agenda

• Concurrency: what, why, how

• Concurrency-related problems

• Locks & Locking strategies

• Concurrent programming with semaphores

2

Page 3: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Concurrency: what, why, how

3

Page 4: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Concurrency (in computing) = two or more overlapping execution contexts

Execution context = a program and associated dynamic state (e.g., PC & stack)

4

Page 5: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Parallelism, requiring multiple CPUs, is one way of realizing concurrency

• That is, computations run at the same time

• …But, concurrency can also be achieved with single-CPU multiplexing

• That is, via context switches

5

Page 6: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

6

concurrency

parallelism

c0 c1 c0 c1context switch

Page 7: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

But, even on multi-CPU systems, CPU multiplexing is performed to achieve higher levels of concurrency

7

Page 8: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Base unit of concurrency: process

• Each execution context “owns” virtualized CPU, memory

• Separate global address space

• Share-nothing architecture

• Context switches triggered, by traps/interrupts

8

Page 9: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

9

int blob = 0;

int main(int argc, const char * argv[]) { pid_t pid; for (int i = 0; i < 5; i++) { if ((pid = fork()) == 0) { blob += 1; printf("Child %d blob = %d\n", i, blob); exit(0); } else { printf("Parent created child %d\n", pid); } } return 0; }

Parent created child 12678 Parent created child 12679 Child 0 blob = 1 Parent created child 12680 Child 1 blob = 1 Child 2 blob = 1 Child 3 blob = 1 Parent created child 12681 Parent created child 12682 Child 4 blob = 1 Program ended with exit code: 0

Page 10: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Process model of concurrency provides system-level sandboxing

• Separate processes cannot—by default—interfere with each other

• Computations are performed entirely independently

• Interprocess communication requires kernel APIs and data structures

10

Page 11: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Within a process, default to a single thread of execution; that is:

• One path through program

• One stack

• Blocking this thread (e.g., with I/O) blocks the entire process

11

Page 12: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

But, the single-thread-per-process model is not always ideal nor sufficient!

May desire intra-process concurrency!

12

Page 13: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Why?

1. Partition blocking activities

2. Improve CPU utilization

3. Performance gains from parallelization (most elusive!

13

Page 14: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

#1. Consider sequential operations that block on unrelated I/O resources

read_from_disk1(buf1); // block for input read_from_disk2(buf2); // block for input read_from_network(buf3); // block for input process_input(buf1, buf2, buf3);

Would like to initiate input from separate blocking resources simultaneously

14

Page 15: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

#2. Consider interleaved but independent CPU & I/O operations

while (1) { long_computation(); // CPU-intensive update_log_file(); // block on I/O }

Would like to start next computation while logging results from previous loop

15

Page 16: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

#3. Consider independent computations over large data set (software SIMD)

#define DIM 5

int A[DIM][DIM], /* src matrix A */ B[DIM][DIM], /* src matrix B */ C[DIM][DIM]; /* dest matrix C */

/* C = A x B */ void matrix_mult() { int i, j, k; for (i = 0; i < DIM; i++) { for (j = 0; j < DIM; j++) { C[i][j] = 0; for (k = 0; k < DIM; k++) { C[i][j] += A[i][k] * B[k][j]; } } } }

16

Each cell in result is independent—need not serialize!

Page 17: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• In each scenario, could make use of multiple threads within a single process

• Permitted to independently block

• Capable of running concurrently

• Take advantage of global address space (i.e., easy sharing of data)

17

Page 18: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Each thread needs to:

• Share the global state (e.g., the code)

• Track its own execution (e.g., on a stack)

• Be given CPU time (i.e., be scheduled)

18

Page 19: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

19

Global (shared) Thread-local

Code Data Stack Regs

t0

t1

context switch

Page 20: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

But, who is responsible for tracking and scheduling threads?

20

Page 21: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Option 1: kernel (aka native) threads

• Kernel maintains metadata for 1 or more threads per process

• Intra-process thread context switch is cheaper (why?) than process context switch, but still requires interrupt/trap

21

Page 22: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Option 2: user-space threads

• Kernel is only aware of “main” thread

• User code creates and tracks multiple thread states (e.g., stacks & register sets)

• Context switches triggered by global timer or manually (cooperatively scheduled threads = “fibers”)

22

Page 23: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Pros/cons discussion.

23

Page 24: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Kernel threads, pros:

• Thread parallelization is possible

• Process scheduler can be reused

• No extra/duplicate work in user space

• Kernel threads, cons:

• Extra kernel metadata to manage

• Context switch requires trap/interrupt

24

Page 25: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• User threads, pros:

• Cheap to create and manage

• Context switches are fast! (in user space)

• User thread, cons:

• Parallelization is not possible

• Main thread blocks = all threads block

• Replicating OS scheduler in user space

25

Page 26: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Cooperatively-scheduled user threads, aka “fibers” can be even lighter weight!

• Little to no scheduling overhead

• Enables fine-grained, application-specific concurrency control

• May greatly reduce problems due to concurrency (coming later)

26

Page 27: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Option 3*: Hybrid threading

• M:N mapping of kernel to user threads

• User code responsible for scheduling tasks in system provided contexts

• Fast context switches + parallelizability, at cost of complexity (user & kernel)

27

Page 28: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Sample threading API: POSIX Threads (“pthreads”)

28

Page 29: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

29

/* Creates a new thread of execution. */ int pthread_create(pthread_t *thread,

const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

/* Causes the calling thread to wait for the termination of the specified thread; thread "reaping" */ int pthread_join(pthread_t thread,

void **value_ptr);

/* Terminates the calling thread. */ void pthread_exit(void *value_ptr);

Page 30: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

30

Thread 0 blob = 10000 Created thread 4297592832 Thread 1 blob = 20000 Created thread 4297592832 Thread 2 blob = 30000 Created thread 4297592832 Thread 3 blob = 40000 Created thread 4297592832 Thread 4 blob = 50000 Created thread 4297592832 Program ended with exit code: 0

Created thread 4297592832 Created thread 4298129408 Thread 0 blob = 10000 Thread 1 blob = 16132 Created thread 4298665984 Thread 2 blob = 26132 Created thread 4299202560 Created thread 4299739136 Thread 3 blob = 36132 Thread 4 blob = 44550 Program ended with exit code: 0

int blob = 0;

void *inc_blob(void *num) { for (int i = 0; i < 10000; i++) { blob += 1; } printf("Thread %d blob = %d\n", (int)num, blob); pthread_exit(NULL); }

int main(int argc, const char * argv[]) { pthread_t tid; for (int i = 0; i < 5; i++) { pthread_create(&tid, NULL, inc_blob, (void *)i); printf("Created thread %ld\n", (long)tid); } pthread_exit(NULL); return 0; }

Run 1:

Run 2: (?!?)

Page 31: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

31

Thread 0 blob = 10000 Created thread 4297592832 Thread 1 blob = 20000 Created thread 4297592832 Thread 2 blob = 30000 Created thread 4297592832 Thread 3 blob = 40000 Created thread 4297592832 Thread 4 blob = 50000 Created thread 4297592832 Program ended with exit code: 0

Created thread 4297592832 Created thread 4298129408 Thread 0 blob = 10000 Thread 1 blob = 16132 Created thread 4298665984 Thread 2 blob = 26132 Created thread 4299202560 Created thread 4299739136 Thread 3 blob = 36132 Thread 4 blob = 44550 Program ended with exit code: 0

int blob = 0;

void *inc_blob(void *num) { for (int i = 0; i < 10000; i++) { blob += 1; } printf("Thread %d blob = %d\n", (int)num, blob); pthread_exit(NULL); }

int main(int argc, const char * argv[]) { pthread_t tid; for (int i = 0; i < 5; i++) { pthread_create(&tid, NULL, inc_blob, (void *)i);

pthread_join(tid, NULL); printf("Created thread %ld\n", (long)tid); } pthread_exit(NULL); return 0; }

Run 1:

Run 2: (?!?)

Page 32: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Note: pthreads API doesn’t specific whether implementation is kernel/user

• Platform dependent

• Most modern Unixes provided kernel-level threading support

32

Page 33: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Sample fiber library: libtask (swtch.com/libtask/)

33

Page 34: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

34

int blob = 0;

void *inc_task(void *num) { for (int i = 0; i < 3; i++) { for (int i = 0; i < 10000; i++) { blob += 1; } printf("Thread %d blob = %d\n", (int)num, blob); taskyield(); /* give up CPU */ }

taskexit(0); }

/* note: libtask provides default main */ void taskmain(int argc, char **argv) { for (int i = 0; i < 5; i++) { taskcreate(inc_task, (void *)i, 32768); /* stack size */ } }

Thread 0 blob = 10000 Thread 1 blob = 20000 Thread 2 blob = 30000 Thread 3 blob = 40000 Thread 4 blob = 50000 Thread 0 blob = 60000 Thread 1 blob = 70000 Thread 2 blob = 80000 Thread 3 blob = 90000 Thread 4 blob = 100000 Thread 0 blob = 110000 Thread 1 blob = 120000 Thread 2 blob = 130000 Thread 3 blob = 140000 Thread 4 blob = 150000 Program ended with exit code: 0

Page 35: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

35

int taskcreate(void (*fn)(void*), void *arg, uint stack) { int id; Task *t;

t = taskalloc(fn, arg, stack); taskcount++; id = t->id; if(nalltask%64 == 0){ alltask = realloc(alltask, (nalltask +64)*sizeof(alltask[0])); if(alltask == nil){ fprint(2, "out of memory\n"); abort(); } } t->alltaskslot = nalltask; alltask[nalltask++] = t; taskready(t); return id; }

static Task* taskalloc(void (*fn)(void*), void *arg, uint stack) { Task *t; sigset_t zero; uint x, y; ulong z;

/* allocate the task and stack together */ t = malloc(sizeof *t+stack); if(t == nil){ fprint(2, "taskalloc malloc: %r\n"); abort(); } memset(t, 0, sizeof *t); t->stk = (uchar*)(t+1); t->stksize = stack; t->id = ++taskidgen; t->startfn = fn; t->startarg = arg;

/* do a reasonable initialization */ memset(&t->context.uc, 0, sizeof t->context.uc); sigemptyset(&zero); sigprocmask(SIG_BLOCK, &zero, &t->context.uc.uc_sigmask);

/* must initialize with current context */ if(getcontext(&t->context.uc) < 0){ fprint(2, "getcontext: %r\n"); abort(); }

return t; }

Page 36: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• taskyield (and related) implementation is entirely in user-space (C & assembly)

• Saves and restores task state (context) out of separately malloc’d stacks

• Initiates coroutine jump (akin to setjmp/longjmp)

36

Page 37: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

37

static void contextswitch(Context *from, Context *to) { if(swapcontext(&from->uc, &to->uc) < 0){ fprint(2, "swapcontext failed: %r\n"); assert(0); } }

int swapcontext(ucontext_t *oucp, const ucontext_t *ucp) { if(getcontext(oucp) == 0) setcontext(ucp); return 0; }

struct ucontext { sigset_t uc_sigmask; mcontext_t uc_mcontext; … };

struct mcontext { … int mc_ebp; … int mc_ecx; int mc_eax; … int mc_eip; int mc_cs; int mc_eflags; int mc_esp; /* machine state */ … };

#define setcontext(u) setmcontext(&(u)->uc_mcontext) #define getcontext(u) getmcontext(&(u)->uc_mcontext)

#define SET setmcontext #define GET getmcontext

SET: movl 4(%esp), %eax … movl 28(%eax), %ebp … movl 72(%eax), %esp pushl 60(%eax) /* new %eip */ movl 48(%eax), %eax ret

.globl GET GET: movl 4(%esp), %eax … movl %ebp, 28(%eax) … movl $1, 48(%eax) /* %eax */ movl (%esp), %ecx /* %eip */ movl %ecx, 60(%eax) leal 4(%esp), %ecx /* %esp */ movl %ecx, 72(%eax)

movl 44(%eax), %ecx /* restore %ecx */ movl $0, %eax ret

Page 38: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Next: return to reason #3 for concurrency (performance)

38

Page 39: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

#define DIM 50

int A[DIM][DIM], /* src matrix A */ B[DIM][DIM], /* src matrix B */ C[DIM][DIM]; /* dest matrix C */

/* C = A x B */ void matrix_mult() { int i, j, k; for (i = 0; i < DIM; i++) { for (j = 0; j < DIM; j++) { C[i][j] = 0; for (k = 0; k < DIM; k++) { C[i][j] += A[i][k] * B[k][j]; } } } }

39

real 0m0.313s user 0m0.310s sys 0m0.002s

Run time, with DIM=50, 500 iterations:

Page 40: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

40

void run_with_thread_per_cell() { pthread_t ptd[DIM][DIM]; int index[DIM][DIM][2]; for (int i = 0; i < DIM; i++) { for (int j = 0; j < DIM; j++) { index[i][j][0] = i; index[i][j][1] = j; pthread_create(&ptd[i][j], NULL, row_dot_col, index[i][j]); } } for (int i = 0; i < DIM; i++) { for (int j = 0; j < DIM; j++) { pthread_join(ptd[i][j], NULL); } } }

void row_dot_col(void *index) { int *pindex = (int *)index; int i = pindex[0]; int j = pindex[1]; C[i][j] = 0; for (int x = 0; x < DIM; x++) { C[i][j] += A[i][x] * B[x][j]; } }

real 1m6.973s user 0m6.320s sys 1m36.200s

Run time, with DIM=50, 500 iterations:

Page 41: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

41

0

1.75

3.5

5.25

7

1 2 4 8 16 32 64 128 256 512

Real

0

3

6

9

12

1 2 4 8 16 32 64 128 256 512

User System

Single processor system, kernel threading,

DIM = 50, 500 iterations

Page 42: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

But, matrix multiplication happens to be an embarrassingly parallelizable computation!

- not typical of concurrent tasks!

42

Page 43: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Computations on shared data are typically independent (and this isn’t always obvious!)

—may impose a cap on parallelizability

43

Page 44: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Amdhal’s law predicts max speedup given two parameters:

• P : parallelizable fraction of program

• N : # of execution cores

44

Page 45: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

45

Max speedup: S =1

PN + (1� P )

†P ! 1;S ! N

‡N ! 1;S ! 1

1� P

Page 46: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

46

20.00

18.00

16.00

14.00

12.00

10.00

8.00

6.00

4.00

2.00

0.00

Spee

dup

1 2 4 8 16

32

64

128

256

512

1024

2048

4096

8192

1638

4

3276

8

6553

6

Number of Processors

Amdahl’s Law

Parallel Portion 50% 75% 90% 95%

source: https://upload.wikimedia.org/wikipedia/commons/e/ea/AmdahlsLaw.svg

Page 47: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Amdahl’s law is based on a fixed problem size with fixed parallelizable fraction

—but we can argue that as we have more computing power we simply tend to throw larger / more granular problem sets at it

47

Page 48: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• E.g.,:

• Graphics processing: keep turning up resolution/detail

• Weather modeling: increase model parameters/accuracy

• Chess/weiqi AI: deeper search tree

48

Page 49: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Gustafson & Barsis posit that:

• We tend to scale problem size to complete in the same amount of time, regardless of the number of cores

• Parallelizable amount of work scales linearly with number of cores

49

Page 50: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Gustafson’s Law computes speedup based on:

• N cores

• non-parallelizable fraction, P

50

Page 51: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Predicted speedup is linear with respect to number of cores!

51

S = N � P · (N � 1)Speedup:

†P ! 1;S ! 1‡P ! 0;S ! N

Page 52: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

52

0

20

40

60

80

100

120

0 20 40 60 80 100 120

Spe

edup

: S

Number of Cores: N

x - 0.1 * (x-1)x - 0.2 * (x-1)x - 0.3 * (x-1)x - 0.4 * (x-1)x - 0.5 * (x-1)x - 0.6 * (x-1)x - 0.7 * (x-1)x - 0.8 * (x-1)x - 0.9 * (x-1)

Page 53: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Amdahl's Law approximately suggests:

• Suppose a car is traveling between two cities 60 miles apart, and has already spent one hour traveling half the distance at 30 mph. No matter how fast you drive the last half, it is impossible to achieve 90 mph average before reaching the second city. Since it has already taken you 1 hour and you only have a distance of 60 miles total; going infinitely fast you would only achieve 60 mph.

• Gustafson's Law approximately states:

• Suppose a car has already been traveling for some time at less than 90mph. Given enough time and distance to travel, the car's average speed can always eventually reach 90mph, no matter how long or how slowly it has already traveled. For example, if the car spent one hour at 30 mph, it could achieve this by driving at 120 mph for two additional hours, or at 150 mph for an hour, and so on.

53

Page 54: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Amdahl’s vs. Gustafson’s:

• Latter has rosier implication for big data analysis / data science

• But not all datasets naturally expand / increase in resolution

• Both street the importance of maximizing the parallelizable fraction

54

Page 55: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Some of the primary challenges of concurrent programming are to:

1. Identity thread interdependencies

2. Identify (1)’s potential ramifications

3. Ensure correctness

55

Page 56: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

56

E.g., final change in count? (expected = 2)

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

Interdependency: shared var count

Page 57: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

57

Factoring in machine-level granularity:

a1 lw (count), %r0 a2 add $1, %r a3 sw %r0, (count)

Thread Ab1 lw (count), %r0 b2 add $1, %r0 b3 sw %r0, (count)

Thread B

Answer: either +1 or +2

Page 58: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Race condition(s) exist when results are dependent on the order of execution or concurrent tasks.

58

Page 59: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Shared resource(s) are the problem

or, more specifically, concurrent mutability of those shared resources

59

Page 60: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

60

Code that accesses shared resource(s) = critical section

Page 61: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Synchronization:

• Time-sensitive coordination of critical sections so as to avoid race conditions

61

Page 62: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

E.g., specific ordering of different threads, or mutually exclusive access to variables

62

Page 63: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Important: try to separate application logic from synchronization details

• Another instance of policy vs. mechanism

• This can be hard to get right!

63

Page 64: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Most common technique for implementing synchronization is via software “locks”

- explicitly required & released by consumer of shared resources

64

Page 65: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Locks & Locking Strategies

65

Page 66: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Basic idea:

• Create a shared software construct that has well defined concurrency semantics

• aka. a “thread-safe” object

• Use this object as a guard for another, un-thread-safe shared resource

66

Page 67: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

67

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

count

TA TB

acquireacqu

ire

Page 68: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

68

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

count

TA TB

acquireacqu

ire

alloca

ted

Page 69: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

69

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

count

TA TB

acquireuse

alloca

ted

Page 70: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

70

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

count

TA TB

acquirerele

aseallo

cated

Page 71: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

71

a1 count = count + 1

Thread Ab1 count = count + 1

Thread B

count

TA TB

useallocated

Page 72: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Locking can be:

• Global (coarse-grained)

• Per-resource (fine-grained)

72

Page 73: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

73

Coarse-grained locking policy

count buff logfile GUI

TA TB TC TD

Page 74: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

74

Coarse-grained locking policy

count buff logfile GUI

TA TB TC TD

Page 75: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

75

Coarse-grained locking policy

count buff logfile GUI

TA TB TC TD

Page 76: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Coarse-grained locking:

• Is (typically) easier to reason about

• Results in a lot of lock contention

• Could result in poor resource utilization—may be impractical for this reason

76

Page 77: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

77

Fine-grained locking policy

count buff logfile GUI

TA TB TC TD

Page 78: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Fine-grained locking:

• May reduce (individual) lock contention

• May improve resource utilization

• Can result in a lot of locking overhead

• Can be much harder to verify correctness!

• E.g., due to problems such as deadlock

78

Page 79: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

79

Deadlock with fine-grained locking policy

count buff logfile GUI

TA TB TC TD

Page 80: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• So far, we have only considered mutual exclusion

• What about instances where we require a specific order of execution?

• Often very difficult to achieve with simple-minded locks

80

Page 81: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Abstraction: Semaphore

81

Stop Clear

Page 82: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

82

Little Book of Semaphores

Page 83: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Semaphore Rules1. When you create the semaphore, you can initialize its value

to any integer, but after that the only operations you are allowed to perform are increment (increase by one) and decrement (decrease by one). You cannot read the current value of the semaphore.

2. When a thread decrements the semaphore, if the result is negative, the thread blocks itself and cannot continue until another thread increments the semaphore.

3. When a thread increments the semaphore, if there are other threads waiting, one of the waiting threads gets unblocked.

83

Page 84: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

84

fred = Semaphore(1)

Initialization syntax:

Page 85: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Operation names?

85

fred.increment_and_wake_a_waiting_process_if_any() fred.decrement_and_block_if_the_result_is_negative()

fred.increment() fred.decrement()

fred.signal() fred.wait()

fred.V() fred.P()

Page 86: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Operation names?

86

fred.increment_and_wake_a_waiting_process_if_any() fred.decrement_and_block_if_the_result_is_negative()

fred.increment() fred.decrement()

fred.signal() fred.wait()

fred.V() fred.P()

Page 87: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• How to use semaphores for synchronization?

1. Identity essential usage “patterns”

2. Solve “classic” synchronization problems

87

Page 88: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Essential synchronization criteria:

1. Avoid starvation

2. Guarantee bounded waiting

3. No assumptions relative speed (of threads)

4. Allow for maximum concurrency

88

Page 89: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Using Semaphores for Synchronization

89

Page 90: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Basic patterns:

I. Rendevous

II. Mutual exclusion (Mutex)

III. Multiplex

IV. Generalized rendezvous / Barrier & Turnstile

90

Page 91: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

I. Rendevous

91

statement a1 statement a2

Thread Astatement b1 statement b2

Thread B

Guarantee: a1 < b2, b1 < a2

Page 92: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

92

statement a1 aArrived.signal() bArrived.wait() statement a2

Thread Astatement b1 bArrived.signal() aArrived.wait() statement b2

Thread B

aArrived = Semaphore(0) bArrived = Semaphore(0)

Page 93: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

93

statement a1 bArrived.wait() aArrived.signal() statement a2

Thread Astatement b1 aArrived.wait() bArrived.signal() statement b2

Thread B

Note: Swapping wait/signal → Deadlock!

Page 94: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

II. Mutual Exclusion

94

count = count + 1

Thread Acount = count + 1

Thread B

Page 95: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

95

mutex.wait() # critical section count = count + 1

mutex.signal()

Thread A Thread B

mutex = Semaphore(1)

mutex.wait() # critical section count = count + 1

mutex.signal()

Page 96: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

III. multiplex = Semaphore(N)

96

multiplex.wait() critical section

multiplex.signal()

Page 97: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

IV. Generalized Rendezvous / Barrier

97

rendevous critical point

Puzzle: Generalize the rendezvous solution. Every thread should run the following code:

Listing 3.2: Barrier code

Page 98: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

98

n = the number of threads count = 0 mutex = Semaphore(1) barrier = Semaphore(0)

Page 99: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

99

rendevous

mutex.wait() count = count + 1

mutex.signal()

if count == n: barrier.signal()

barrier.wait() barrier.signal()

critical point

Page 100: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

100

rendevous

mutex.wait() count = count + 1

mutex.signal()

if count == n: turnstile.signal()

turnstile.wait() turnstile.signal()

critical point

State of turnstile after all threads make it to critical point?

Page 101: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

101

rendevous

mutex.wait() count = count + 1 if count == n: turnstile.signal()

mutex.signal()

turnstile.wait() turnstile.signal()

critical point

Fix for non-determinism (but still off by one)

Page 102: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Next: would like a reusable barrier

Need to re-lock turnstile

102

Page 103: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

103

rendevous

mutex.wait() count = count + 1 if count == n: turnstile.signal()

mutex.signal()

turnstile.wait() turnstile.signal()

critical point

mutex.wait() count = count - 1 if count == 0: turnstile.wait()

mutex.signal()

(Doesn’t work!)

Page 104: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

104

#rendevous

mutex.wait() count = count + 1 if count == n:

turnstile2.wait() # lock the second turnstile.signal() # unlock the first

mutex.signal()

turnstile.wait() # first turnstile turnstile.signal()

#critical point

mutex.wait() count = count - 1 if count == 0:

turnstile.wait() # lock the first turnstile2.signal() # unlock the second

mutex.signal()

turnstile2.wait() # second turnstile turnstile2.signal()

turnstile = Semaphore(0) turnstile2 = Semaphore(1) mutex = Semaphore(1)

Page 105: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

105

#rendevous

mutex.wait() count = count + 1 if count == n:

turnstile.signal(n) # unlock the first mutex.signal()

turnstile.wait() # first turnstile

#critical point

mutex.wait() count = count - 1 if count == 0:

turnstile2.signal(n) # unlock the second mutex.signal()

turnstile2.signal() # second turnstile

Page 106: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Next: classic synchronization problems

106

Page 107: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

I. Producer / Consumer

107

Page 108: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

108

Assume that producers perform the following operations over and over:

event = waitForEvent() buffer.add(event)

Listing 4.1: Basic producer code

Also, assume that consumers perform the following operations:

event = buffer.get() event.process()

Listing 4.2: Basic consumer code

Important: buffer is finite and non-thread-safe!

Page 109: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

109

- finite, non-thread-safe buffer - 1 semaphore per item/spacemutex = Semaphore(1) items = Semaphore(0) spaces = Semaphore(buffer.size())

Page 110: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

110

items.wait() mutex.wait()

event = buffer.get() mutex.signal() spaces.signal()

event.process()

Listing 4.11: Finite buffer consumer solution

event = waitForEvent()

spaces.wait() mutex.wait()

buffer.add(event) mutex.signal() items.signal()

Listing 4.12: Finite buffer producer solution

Page 111: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

II. Readers/Writers

111

Page 112: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Categorical mutex

112

Page 113: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

113

int readers = 0 mutex = Semaphore(1) roomEmpty = Semaphore(1)

Listing 4.13: Readers-writers initialization

Page 114: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

114

roomEmpty.wait() critical section for writers

roomEmpty.signal()

Listing 4.14: Writers solution

Page 115: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

115

mutex.wait() readers += 1 if readers == 1:

roomEmpty.wait() # first in locks mutex.signal()

# critical section for readers

mutex.wait() readers -= 1 if readers == 0:

roomEmpty.signal() # last out unlocks mutex.signal()

Listing 4.14: Readers solution

Page 116: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

→ “lightswitch” pattern

116

Page 117: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

117

class Lightswitch: def __init__(self):

self.counter = 0 self.mutex = Semaphore(1)

def lock(self, semaphore): self.mutex.wait()

self.counter += 1 if self.counter == 1:

semaphore.wait() self.mutex.signal()

def unlock(self, semaphore): self.mutex.wait()

self.counter -= 1 if self.counter == 0:

semaphore.signal() self.mutex.signal()

Listing 4.16: Lightswitch definition

Page 118: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

118

readLightswitch = Lightswitch() roomEmpty = Semaphore(1)

Listing 4.17: Readers-writers initialization

readLightswitch is a shared Lightswitch object whose counter is initially zero.

readLightswitch.lock(roomEmpty) # critical section readLightswitch.unlock(roomEmpty)

Listing 4.18: Readers-writers solution (reader)

Page 119: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Recall criteria:

1. No starvation

2. Bounded waiting

… but writer can starve!

119

Page 120: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Need a mechanism for the writer to prevent new readers from getting “around” it (and into the room)

i.e., “single-file” entry

120

Page 121: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

121

readSwitch = Lightswitch() roomEmpty = Semaphore(1) turnstile = Semaphore(1)

Listing 4.19: No-starve readers-writers initialization

Page 122: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

122

turnstile.wait() roomEmpty.wait() # critical section for writers

turnstile.signal()

roomEmpty.signal()

Listing 4.20: No-starve writer solution

turnstile.wait() turnstile.signal()

readSwitch.lock(roomEmpty) # critical section for readers

readSwitch.unlock(roomEmpty)

Listing 4.21: No-starve reader solution

Page 123: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Exercise for the reader: writer priority?

123

Page 124: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Bounded waiting?

• Simple if we assume that threads blocking n a semaphore are queued (FIFO)

• I.e., thread blocking longest is woken next

• But semaphore semantics don’t require this

124

Page 125: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

→ FIFIO queue pattern

Goal: use semaphores to build a thread-safe FIFO wait queue

Given: non-thread-safe queue

125

Page 126: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Approach:

• Protect queue with shared mutex

• Each thread enqueues its own thread-local semaphores and blocks on it

• To signal, dequeue & unblock a semaphore

126

Page 127: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

127

class FifoSem: def __init__(self, val):

self.val = val # FifoSem’s semaphore value self.mutex = Semaphore(1) # possibly non-FIFO semaphore self.queue = dequeue() # non-thread-safe queue

def wait(self): barrier = Semaphore(0) # thread-local semaphore block = False self.mutex.wait() # modify val & queue in mutex

self.val -= 1 if self.val < 0:

self.queue.append(barrier) block = True

self.mutex.signal() if block:

barrier.wait() # block outside mutex!

def signal(self): self.mutex.wait() # modify val & queue in mutex

self.val += 1 if self.queue: barrier = self.queue.popleft() # FIFO! barrier.signal()

self.mutex.signal()

Page 128: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

From here on out, we will assume that all semaphores have built-in FIFO semantics

128

Page 129: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

129

III. “Dining Philosophers” problem

Page 130: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

130

forks = [Semaphore(1) for i in range(5)]

Listing 4.30: Variables for dining philosophers

Typical setup: protect shared resources with semaphores

def left(i): return i def right(i): return (i + 1) % 5

Listing 4.29: Which fork?

Page 131: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Solution requirements:

1. Each fork held by one philosopher at a time

2. No deadlock

3. No philosopher may starve

4. Max concurrency should be possible

131

Page 132: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

132

Naive solution:def get_forks(i):

fork[right(i)].wait() fork[left(i)].wait()

def put_forks(i): fork[right(i)].signal() fork[left(i)].signal()

Possible deadlock!

Page 133: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

133

Solution 2: global mutexdef get_forks(i):

mutex.wait() fork[right(i)].wait() fork[left(i)].wait()

mutex.signal()

No starvation & max concurrency?May prohibit a philosopher from eating when his forks are available

Page 134: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

134

Solution 3: limit # of dinersfootman = Semaphore(4)

No starvation & max concurrency?

def get_forks(i): footman(wait) fork[right(i)].wait() fork[left(i)].wait()

def put_forks(i): fork[right(i)].signal() fork[left(i)].signal() footman.signal()

Page 135: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

135

Solution 4: leftie(s) vs. rightie(s)

vs. (at least one of each)

def get_forks(i): fork[right(i)].wait() fork[left(i)].wait()

def get_forks(i): fork[left(i)].wait() fork[right(i)].wait()

No starvation & max concurrency?

Page 136: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

136

Solution 4: Tanenbaum’s solutionstate = [‘thinking’] * 5 sem = [Semaphore(0) for i in range(5)] mutex = Semaphore(1)

def get_fork(i): mutex.wait()

state[i] = ‘hungry’ test(i) # check neighbors’ states

mutex.signal() sem[i].wait() # wait on my own semaphore

def put_fork(i): mutex.wait()

state[i] = ‘thinking’ test(right(i)) # signal neighbors if they can eat test(left(i))

mutex.signal()

def test(i): if state[i] == ‘hungry’ \

and state[left(i)] != ‘eating’ \ and state[right(i)] != ‘eating’:

state[i] = ‘eating’ sem[i].signal() # this signals me OR a neighbor

No starvation & max concurrency?

Page 137: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

137

T

T

T

T

T

Page 138: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

138

T

T

T

H

T

Page 139: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

139

T

T

T

E

T

Page 140: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

140

H

T

T

E

T

Page 141: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

141

E

T

T

E

T

Page 142: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

142

E

T

T

E

H

Page 143: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

143

E

H

T

E

H

Page 144: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

144

E

H

H

E

H(Let’s mess with this guy)

Page 145: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

145

T

H

H

E

H

Page 146: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

146

T

E

H

E

H

Page 147: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

147

T

E

H

T

H

Page 148: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

148

T

E

E

T

H

Page 149: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

149

T

E

E

T

Page 150: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

150

H

E

T

H

Page 151: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

151

H

E

T

E

Page 152: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

152

H

T

T

E

Page 153: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

153

E

T

T

E

Page 154: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

154

E

H

H

E

Page 155: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

155

H

E

E

H

Page 156: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

156

E

H

H

E

Page 157: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

157

H

(starves)

Page 158: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Moral of the story: synchronization problems are insidious!

158

Page 159: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

159

IV. Dining Savages

Page 160: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

160

A tribe of saves eats communal dinners from a large pot that can hold M servings of stewed missionary. When a savage wants to eat, he helps himself from the pot, unless it is empty. If the pot is empty, the savage wakes up the cook and then waits until the cook has refilled the pot.

while True: getServingFromPot() eat()

Listing 5.1: Unsynchronized savage code

And one cook thread runs this code:

while True: putServingsInPot(M)

Listing 5.2: Unsynchronized cook code

Page 161: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

161

while True: getServingFromPot() eat()

Listing 5.1: Unsynchronized savage code

And one cook thread runs this code:

while True: putServingsInPot(M)

Listing 5.2: Unsynchronized cook code

Rules: • Savages cannot invoke getServingFromPot

if the pot is empty • The cook can invoke putServingsInPot only

if the pot is empty

Page 162: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

162

while True: getServingFromPot() eat()

Listing 5.1: Unsynchronized savage code

And one cook thread runs this code:

while True: putServingsInPot(M)

Listing 5.2: Unsynchronized cook code

hint: servings = 0 mutex = Semaphore(1) emptyPot = Semaphore(0) fullPot = Semaphore(0)

Page 163: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

163

while True: emptyPot.wait() putServingsInPot(M) fullPot.signal()

Listing 5.4: Dining Savages solution (cook)

while True: mutex.wait()

if servings == 0: emptyPot.signal() fullPot.wait() servings = M

servings -= 1 getServingFromPot()

mutex.signal()

eat()

Listing 5.5: Dining Savages solution (savage)

Page 164: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

Shared servings counter → scoreboard pattern

• Arriving threads check value of scoreboard to determine system state

• Note: scoreboard may consist of more than one variable

164

Page 165: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

165

V. Baboon Crossing

Page 166: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

166

eastwest

Page 167: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

167

Page 168: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

168

Page 169: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

169

Guarantee rope mutex

Page 170: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

170

Max of 5 at a time

Page 171: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

171

No starvation

Page 172: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

• Solution consists of east & west baboon threads:

• Categorial mutex

• Max of 5 on rope

• No starvation

172

Page 173: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

173

while True: climbOnRope() CrossChasm()

Unsynchronized baboon code (identical for both sides)

hint: multiplex = Semaphore(5) turnstile = Semaphore(1) rope = Semaphore(1) e_switch = Lightswitch() w_switch = Lightswitch()

Page 174: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

174

class Lightswitch: def __init__(self):

self.counter = 0 self.mutex = Semaphore(1)

def lock(self, semaphore): self.mutex.wait()

self.counter += 1 if self.counter == 1:

semaphore.wait() self.mutex.signal()

def unlock(self, semaphore): self.mutex.wait()

self.counter -= 1 if self.counter == 0:

semaphore.signal() self.mutex.signal()

Reminder: Lightswitch ADT

Page 175: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

175

multiplex = Semaphore(5) turnstile = Semaphore(1) rope = Semaphore(1) e_switch = Lightswitch() w_switch = Lightswitch()

while True: # west side turnstile.wait() w_switch.lock(rope) turnstile.signal()

multiplex.wait() climbOnRope() crossChasm() multiplex.signal()

w_switch.unlock(rope)

while True: # east side turnstile.wait() e_switch.lock(rope) turnstile.signal()

multiplex.wait() climbOnRope() crossChasm() multiplex.signal()

e_switch.unlock(rope)

Page 176: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

176

multiplex = Semaphore(5) turnstile = Semaphore(1) rope = Semaphore(1) mutex_east = Semaphore(1) mutex_west = Semaphore(1) east_count = west_count = 0

# west side turnstile.wait() mutex_west.wait()

west_count++ if west_count == 1:

rope.wait() mutex_west.signal() turnstile.signal()

multiplex.wait() # cross the chasm

multiplex.signal()

mutex_west.wait() west_count-- if west_count == 0:

rope.signal() mutex_west.signal()

# east side turnstile.wait() mutex_east.wait()

east_count++ if east_count == 1:

rope.wait() mutex_east.signal() turnstile.signal()

multiplex.wait() # cross the chasm

multiplex.signal()

mutex_east.wait() east_count-- if east_count == 0:

rope.signal() mutex_east.signal()

Page 177: Concurrency, Races, & Synchronizationbluesky.cs.iit.edu/cs450/slides/06-Concurrency_and...Concurrency,Races, & Synchronization CS 450: Operating Systems Sean Wallace

… many, many more contrived problems await you in the Little Book of Semaphores!

177


Recommended