concurrent programming
DESCRIPTION
Concurrent Programming. Outline. Topics: Shared variables Synchronizing with semaphores Suggested reading: 12.4~12.5. Approaches to Concurrency. Processes Hard to share resources: easy to avoid unintended sharing High overhead in adding/removing clients Threads - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/1.jpg)
1
Concurrent Programming
![Page 2: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/2.jpg)
2
Outline
• Topics:– Shared variables
– Synchronizing with semaphores
• Suggested reading:– 12.4~12.5
![Page 3: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/3.jpg)
Approaches to Concurrency
• ProcessesProcesses– Hard to share resources: easy to avoid unintended sharing– High overhead in adding/removing clients
• ThreadsThreads– Easy to share resources: Perhaps too easy– Medium overhead– Not much control over scheduling policies– Difficult to debug: event orderings not repeatable
• I/O MultiplexingI/O Multiplexing– Tedious and low level– Total control over scheduling– Very low overhead– Cannot create as fine grained a level of concurrency– Does not make use of multi-core
![Page 4: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/4.jpg)
4
Traditional view of a process
• Process = process context + code, data, and stack
shared libraries
run-time heap
0
read/write data
Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC)Kernel context: VM structures Descriptor table brk pointer
Code, data, and stack
read-only code/data
stackSP
PC
brk
Process context
![Page 5: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/5.jpg)
5
Alternate view of a process
• Process = thread + code, data, and kernel context
shared libraries
run-time heap
0
read/write dataThread context: Data registers Condition codes Stack pointer (SP) Program counter (PC)
Code and Data
read-only code/data
stackSP
PC
brk
Thread (main thread)
Kernel context: VM structures Descriptor table brk pointer
![Page 6: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/6.jpg)
6
A process with multiple threads
• Multiple threads can be associated with a process– Each thread has its own logical control flow
(sequence of PC values)
– Each thread shares the same code, data, and kernel context
– Each thread has its own thread id (TID)
![Page 7: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/7.jpg)
7
A process with multiple threads
shared libraries
run-time heap
0
read/write dataThread 1 context: Data registers Condition codes SP1 PC1
Shared code and data
read-only code/data
stack 1
Thread 1 (main thread)
Kernel context: VM structures Descriptor table brk pointer
Thread 2 context: Data registers Condition codes SP2 PC2
stack 2
Thread 2 (peer thread)
![Page 8: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/8.jpg)
Logical View of Threads
• Threads associated with process form a pool of peers– Unlike processes which form a tree hierarchy
P1
sh sh sh
foo
bar
T1
Process hierarchyThreads associated with process foo
T2T4
T5 T3
shared code, dataand kernel context
P0
![Page 9: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/9.jpg)
9
Pros and cons of thread-based designs
• + Easy to share data structures between threads– e.g., logging information, file cache.
• + Threads are more efficient than processes
• - Unintentional sharing can introduce subtle and hard-to-reproduce errors!– The ease with which data can be shared is
both the greatest strength and the greatest weakness of threads
– Hard to know which data shared & with private
![Page 10: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/10.jpg)
10
Shared variables in threaded C programs
• Which variables in a C program are shared or not?– What is the memory model for threads?
– How are instances of the variable mapped to memory?
– How many threads reference each of these instances?
![Page 11: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/11.jpg)
11
Threads memory model
• Conceptual model:
– Each thread runs in the context of a process.
– Each thread has its own separate thread context
• Thread ID, stack, stack pointer, program counter,
condition codes, and general purpose registers
– All threads share the remaining process context
• Code, data, heap, and shared library segments of the
process virtual address space
• Open files and installed handlers
![Page 12: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/12.jpg)
12
Threads memory model
• Operationally, this model is not strictly
enforced:
– While register values are truly separate and
protected....
– Any thread can read and write the stack of any
other thread.
The MISMATCH between the CONCEPTUAL and OPERATION MODEL is a source of confusion and errors
![Page 13: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/13.jpg)
13
Shared variable analysis
1 #include "csapp.h"
2 #define N 2
3 void *thread(void *vargp);
4
5 char **ptr; /* global variable */
6
![Page 14: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/14.jpg)
14
Shared variable analysis
7 int main()
8 {
9 int i;
10 pthread_t tid;
11 char *msgs[N] = {
12 "Hello from foo",
13 "Hello from bar"
14 };
15
16 ptr = msgs;
17 for (i = 0; i < N; i++)
18 Pthread_create(&tid, NULL, thread, (void *)i);
19 Pthread_exit(NULL);
20 }
1 #include "csapp.h"2 #define N 23 void *thread(void *vargp);45 char **ptr; 6 /* global variable */
![Page 15: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/15.jpg)
15
Shared variable analysis
21 void *thread(void *vargp)
22 {
23 int myid = (int)vargp;
24 static int cnt = 0;
25
26 printf("[%d]:%s(cnt=%d)\n", myid, ptr[myid], ++cnt);
27 }
![Page 16: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/16.jpg)
Mapping Variable Instances to Memory
• Global variables– Def: Variable declared outside of a function– Virtual memory contains exactly one instance of any
global variable
• Local variables– Def: Variable declared inside function without static
attribute– Each thread stack contains one instance of each local
variable
• Local static variables– Def: Variable declared inside function with the static
attribute– Virtual memory contains exactly one instance of any local
static variable.
![Page 17: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/17.jpg)
17
Shared variable analysis
• Which variables are shared?
Variable Referenced by Referenced by Referenced byinstance main thread? peer thread-0? peer thread-1?ptr yes yes yescnt no yes yesi.m yes no nomsgs.m yes yes yesmyid.p0 no yes nomyid.p1 no no yes
![Page 18: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/18.jpg)
18
Shared variable analysis
• Answer: A variable x is shared iff multiple threads reference at least one instance of x
• Thus:– ptr, cnt, and msgs are shared.– i and myid are NOT shared.
![Page 19: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/19.jpg)
19
Shared variable analysis
9 int main()10 {11 pthread_t tid1, tid2;1213 Pthread_create(&tid1, NULL, count, NULL);14 Pthread_create(&tid2, NULL, count, NULL);15 Pthread_join(tid1, NULL);16 Pthread_join(tid2, NULL);1718 if (cnt != (unsigned)NITERS*2)19 printf("BOOM! cnt=%d\n", cnt);20 else21 printf("OK cnt=%d\n", cnt);22 exit(0);23 }
1 #include "csapp.h"23 #define NITERS 1000000004 void *count(void *arg);56 /* shared variable */7 unsigned int cnt = 0;8
![Page 20: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/20.jpg)
20
Shared variable analysis
24
25 /* thread routine */
26 void *count(void *arg)
27 {
28 int i;
29 for (i=0; i<NITERS; i++)
30 cnt++;
31 return NULL;
32 }
![Page 21: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/21.jpg)
21
Shared variable analysis
• cnt should be equal to 200,000,000. • What went wrong?!
linux> badcntBOOM! cnt=198841183
linux> badcntBOOM! cnt=198261801
linux> badcntBOOM! cnt=198269672
![Page 22: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/22.jpg)
22
for (i=0; i<NITERS; i++)for (i=0; i<NITERS; i++) cnt++;cnt++;
C code for thread i
Assembly code for counter loop
![Page 23: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/23.jpg)
23
.L9:movl -4(%ebp),%eax #i:-4(%ebp)cmpl $99999999,%eaxjle .L12jmp .L10
.L12:movl cnt,%eax # Loadleal 1(%eax),%edx # Updatemovl %edx,cnt # Store
.L11:movl -4(%ebp),%eaxleal 1(%eax),%edxmovl %edx,-4(%ebp)jmp .L9
.L10:
Asm code for thread i
Head (Hi)
Tail (Ti)
Load cnt (Li)Update cnt (Ui)Store cnt (Si)
Assembly code for counter loop
![Page 24: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/24.jpg)
24
Concurrent execution
• Key idea: In general, any sequentially
consistent interleaving is possible, but
some are incorrect!
– Ii denotes that thread i executes instruction I
– %eaxi is the contents of %eax in thread i’s
context
![Page 25: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/25.jpg)
25
Concurrent execution
H1
L1
U1
S1
H2
L2
U2
S2
T2
T1
1111222221
-011-
-
-
-
-
1
0001111222
i(thread) instri cnt%eax1
OK
----
-
1222-
%eax2
![Page 26: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/26.jpg)
26
Concurrent execution (cont)
• Incorrect ordering: two threads increment the counter, but the result is 1 instead of 2.
H1
L1
U1
H2
L2
S1
T1
U2
S2
T2
1
1
1
2
2
1
1
2
2
2
-
0
1
-
-
1
1
-
-
-
0
0
0
0
0
1
1
1
1
1
i(thread) instri cnt%eax1
-
-
-
-
-
-
1
1
1
%eax2
0
![Page 27: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/27.jpg)
27
A progress graph depictsthe discrete execution state space of concurrent threads.
Each axis corresponds tothe sequential order ofinstructions in a thread.
Each point corresponds toa possible execution state(Inst1, Inst2).
E.g., (L1, S2) denotes statewhere thread 1 hascompleted L1 and thread2 has completed S2.
H1 L1 U1 S1 T1
H2
L2
U2
S2
T2
Thread 1
Thread 2
(L1, S2)
Progress graphs
![Page 28: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/28.jpg)
28
A trajectory is a sequence of legal state transitions that describes one possible concurrent execution ofthe threads.
Example:
H1, L1, U1, H2, L2, S1, T1, U2, S2, T2
H1 L1 U1 S1 T1
H2
L2
U2
S2
T2
Thread 1
Thread 2
Trajectories in progress graphs
![Page 29: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/29.jpg)
29
L, U, and S form a critical section withrespect to the sharedvariable cnt.
Instructions in criticalsections (write to someshared variable) should not be interleaved.
Sets of states where suchinterleaving occursform unsafe regions.
H1 L1 U1 S1 T1
H2
L2
U2
S2
T2
Thread 1
Thread 2
Unsafe region
critical section wrt cnt
critical section wrt cnt
Critical sections and unsafe regions
![Page 30: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/30.jpg)
30
Def: A trajectory is safe iff it doesn’t touch any part of an unsafe region.
Claim: A trajectory is correct (write cnt) iff it is safe.
critical section wrt cnt
H1 L1 U1 S1 T1
H2
L2
U2
S2
T2
Thread 1
Thread 2
Unsafe region Unsafetrajectory
Safe trajectory
critical section wrt cnt
Safe and unsafe trajectories
![Page 31: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/31.jpg)
31
Synchronizing with semaphores
• Dijkstra's P and V operations on
semaphores
– semaphoresemaphore: non-negative integer
synchronization variable.
• P(s): [ while (s == 0) wait(); s--; ]
– Dutch for "Proberen" (test)
• V(s): [ s++; ]
– Dutch for "Verhogen" (increment)
![Page 32: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/32.jpg)
32
Synchronizing with semaphores
• Dijkstra's P and V operations on
semaphores
– OS 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 33: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/33.jpg)
33
#include <semaphore.h>
int sem_init(sem_t *sem, 0, unsigned int value);int sem_wait(sem_t *s); /* P(s) */int sem_post(sem_t *s); /* V(s) */
#include “csapp.h”
void P(sem_t *s); /* Wrapper function for sem_wait */void V(sem_t *s); /* Wrapper function for sem_wait */
POSIX semaphores
![Page 34: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/34.jpg)
34
#include "csapp.h"#define NITERS 10000000unsigned int cnt; /* counter */sem_t sem; /* semaphore */
int main() { pthread_t tid1, tid2; Sem_init(&sem, 0, 1); /* create 2 threads and wait */ ... if (cnt != (unsigned)NITERS*2) printf("BOOM! cnt=%d\n", cnt); else printf("OK cnt=%d\n", cnt); exit(0);}
Sharing with POSIX semaphores
![Page 35: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/35.jpg)
35
/* thread routine */void *count(void *arg){ int i;
for (i=0; i<NITERS; i++) { P(&sem); cnt++; V(&sem); } return NULL;}
Sharing with POSIX semaphores
![Page 36: Concurrent Programming](https://reader034.vdocuments.net/reader034/viewer/2022051623/568157f2550346895dc56d8d/html5/thumbnails/36.jpg)
36
Provide mutually exclusive access to shared variable by surrounding critical section with P and V operations on semaphores (initially set to 1).
Semaphore invariant creates a forbidden regionthat encloses unsafe region and is never touched by any trajectory.
H1 P(s) V(s) T1 Thread 1
Thread 2
L1 U1 S1
H2
P(s)
V(s)
T2
L2
U2
S2
Unsafe region
Forbidden regionForbidden region
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
0 0 -1 -1 -1 -1 0 0
0 0-1 -1 -1 -1
0 0
0 0 -1 -1 -1 -1 0 0
0 0-1 -1 -1 -1
0 0
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
Initiallys = 1
Safe sharing with semaphores