SLIDE 1
Feb 2 2009 1:10 Page 1
synchronization.txt
A summary of the synchronization lecture (and additions) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− main int i = 0; start thread A start thread B wait for threads to finish printf("value of i: %d\n", i); thread A ++i thread B ++i The instructions executed to increase i would be:
- 1. Copy value of i to register eax
- 2. Increase value of register by 1
- 3. Copy value of register eax to i
We first assume one CPU and that thread A completed before thread B
- starts. Indicating the instruction order by thread name and
instruction number we have: A1 A2 A3 B1 B2 B3 i 0 0 0 1 1 1 2 Executing the instructions you find that the final value of i is 2. Since it is increased two times this is correct and expected. Next we assume a timer interrupt causing a thread switch between instruction A2 and A3. Assuming thread B is picked from the ready queue the ins ruction sequence become: A1 A2 B1 B2 B3 A3 i 0 0 0 0 0 0 1 The final value of i become 1. Since we still have the same program that increase i twice this is unexpected and wrong. What happened? Both threads read the initial value of i (A1 and B1), and then A3
- verwrote the result of B3.
Finally we assume two CPUs ant that the threads run truly simultaneous. We assume thread B start a fraction of time after A. A1 A2 A3 B1 B2 B3 We have a similar result as previously. Both threads read the initial value of i and B3 will overwrite the result of A3 (loosing it). Using threads a above the result is not deterministic. Clearly not
- acceptable. A program should always return a deterministic correct
- result. How do we solve the situation?
First, we try to let each thread put up a sign "I’m modifying i, you’ll have to wait". The new program: main int i = 0; bool busy = false; start thread A start thread B wait for threads to finish printf("value of i: %d\n", i);
Feb 2 2009 1:10 Page 2
synchronization.txt
thread A and B 1 while (busy) ; 2 busy = true; 3 copy i to eax 4 increment eax 5 copy eax to i 6 busy = false; Let us still assume a interrupt and thread switch at same code as before, now between A4 and A5: A1 A2 A3 A4 B1 B1 B1 B1 B1 B1 ... busy f f t t t t t t t t t i 0 0 0 0 0 0 0 0 0 0 0 Since busy is now true B will get stuck in the loop ... until a new thread switch, we assume A continue: A5 A6 B2 B3 B4 B5 B6 busy t t f t t t t f i 0 1 1 1 1 1 2 2 When A6 has been executed B can continue (once B is scheduled again). The result is now correct again. One problem we can see here is that thread B is wasting a lot of CPU time. B occupies the CPU to determine when to stop waiting, this is called "busy−wait" and is a waste of CPU
- time. Really bad. But that’s not all.