CS 361 Concurrent programming Drexel University Fall 2004 Lecture 8 Bruce Char and Vera Zaychik. All rights reserved by the author. Permission is given to students enrolled in CS361 Fall 2004 to reproduce these notes for their own use. Peterson s attempt (mutual exclusion for two threads) public void wanttoentercs(int I) { // preprotocol desirecs[i].value = true; last = other(i); while (desirecs[other(i)].value && last == other(i)) public void finishedincs(int I) { // postprotocol desirecs[i].value=false; page 1 page 2 Proof of correctness Prove that the algorithm enforces mutual exclusion correctly by showing that it is impossible for two threads to be in the critical section simultaneously. doesn t allow deadlock (i.e. it s impossible). doesn t allow starvation in the presence of contention doesn t allow starvation in the absence of contention A separate proof for each point, each done as a proof by contradiction. Proof by contradiction If you show that assuming p leads you to conclude something which you know to be false, then you are forced to conclude that there are no circumstances when p is true in other words, p must be false all the time. ( p p page 3 page 4 We talk about two threads running Peterson s algorithm. We assume that they violate ME (call this assumption v). We show that assuming v leads to the conditions that contradict the threads programming. In particular, we conclude s: that each thread set a variable last to different values. We know this violates the rules of programming languages, in other words: s=false. v Since we have shown v=>false, we conclude that the two threads cannot violate ME if they follow Peterson s algorithm. page 5 Game plan for proof by contradiction page 6 Proof of mutual exclusion property Some observations on Peterson s code: the only values that last can take on are 0 and 1. Each thread can enter its critical section only if!( desirecs.value[other(i)] && last == other(i)). That is, either desirecs.value[other(i)] is false or last = = i. Start of proof by contradiction: Assume that this algorithm does not support mutual exclusion. So there must be a scenario where both threads end up in the CS at once.
Proofs by contradiction when the world is divided into two cases Show each case separately: page 7 ( v ( v true ( v ( case1 case2) (( v case1) (( v case2) Proof of mutual exclusion, case 1 Suppose one thread (say, 0) gets through the preprotocol (evaluates the while condition) before the other thread has finished executing any lines of it (before it has set its value flag to true). It s then easy to see that the second thread will get stuck in the loop until the first thread does the postprotocol. This contradicts the assumption that both threads get into the CS at once. We get a similar contradiction if we assume that thread 1 gets in first and thread 0 lags. There are actually two subcases (case1a,case1b) we ve shown case1a and the proof for case1b is page 8 similar. What s false. ME violation Thread 0 gets into CS Thread 1 gets into CS Thread 0 gets into CS first Thread 1 does not get into CS An easy toprovefact: ( p q1 q2 r q2) false One case down, one to go We ve taken the assumption in case1 to prove something that we know is false. So we now need to prove that the assumptions in case2 also lead to false. Case 2 is not case 1 : a scenario where there is overlap in the preprotocol: one thread finishes at least the first instruction before the other thread begins execution of its last one. page 9 page 10 Case 2a: thread #0 ahead of #1 but both in preprotocol at once public void wanttoentercs(int I) { // preprotocol desirecs[i].value = true; (A) last = other(i); (B) while (desirecs[other(i)].value && last == other(i)) (C) We are assuming thread #1 has done A before #0 does C. So when thread #0 does C, last==0 (!=other(0)) or else thread #0 will loop instead of get into the CS. Thread #1 must have set last after Thread #0 set it. page 11 page 12 Case 2a, continued. When thread #1 checks its while loop condition, we know that desirecs[0].value is true because Thread #0 has already done it. So the only way that thread #1 can fall out of the while loop is if last=1. But we know that at that point when Thread #1 does this check, it has already done last=0. So it must be that Thread 0 has set last after Thread 1. We have deduced that if both threads get into the critical section, each must have set last last (to different values). This is false (based on what we know about the way programs and variables behave).
page 13 Proof of mutual exclusion (the conclusion) There is a case2b, where Thread #1 is ahead of Thread #0. We find a similar problem then. We assumed that the algorithm failed to provide mutual exclusion. From this we were led to two kinds cases: (overlap/no overlap of execution of the preprotocol). In both cases, we found that assuming that the algorithm allows violations of mutual exclusion leads to something we know is false (that both threads get into the CS while one is stuck in the pre-protocol, or that last has two values at the same time). page 14 Proof of mutual exclusion (the finale) We can conclude that it is impossible for the algorithm to violate mutual exclusion. Avoiding double negatives, another way of saying this is that the algorithm guarantees mutual exclusion: at most one thread is permitted into the critical section at a time. Proof of starvation in the absence of contention If thread 0 is not interested in entering its CS, then its flag is false and so thread 1 can enter because the while loop will not block it. Similar argument for thread 1. Proof for no starvation in the presence of contention We prove this by contradiction. Assume that thread 0 is frustrated while thread 1 tries and succeeds repeatedly. We will show that assuming this leads us to prove a statement we know is false. page 15 page 16 Proof in the presence of contention, con t If thread 0 has entered the preprotocol and has set desirecs[0] to true but is stuck it must be executing its while statement repeatedly. Thus desirecs[1] is true and last==0, at least while thread 0 is repeating. But this means that thread 1 will enter its critical section if it hasn t already Once it leaves its critical section, it will reset desirecs[1] to false. Proof in presence of contention, con t What can happen after thread 1 leaves its post protocol Either thread 1 whips around into its preprotocol and sets desirecs[1] to true again before thread 0 notices, or Or thread 0 notices that desirecs[1] is false before thread 1 tries to re-enter the preprotocol. It proceeds into the CS which again is a contradiction of our original assumption. page 17 page 18
What happens when thread 1 enters the preprotocol again After setting desirecs[1] to true again, thread 1 will then set last to 0. It will hang up in its loop. Thread 0 will wake up (because of the yield) and stop looping because its while condition is no longer true. It will proceed into the CS. This again contradicts our assumption that thread 0 was hopelessly stuck. Completed proof of no starvation in presence of contention Thus in all cases, assuming that thread 0 is stuck in its loop forever produces a contradiction. So it s impossible -- thread 0 must enter its CS after at most one entry by thread 1. page 19 page 20 Conclusion of proof of no starvation A similar argument can be made for thread 1 being stuck forever. We have to check this, but it really goes through by a mechanical substitution of 0 for 1 and vice versa in our original argument. These are all the possibilities for threads getting starved with contention. We end up with a contradiction in each case. No deadlock If both threads are stuck in the critical section, then they both must be looping. Once they are looping, neither can change the value of last or their desirecs values. For both to loop, both threads have set their desirecs values to true. For both to loop, last must be both 0 and 1 at the same time. This is impossible (violates the rules of programming) page 21 page 22 Peterson s attempt (Hartley s way) public void wanttoentercs(int i) { // preprotocol desirecs[i].value = true; last = i; while (desirecs[other(i)].value && last == i) public void finishedincs(int i) { // postprotocol desirecs[i].value=false; Peterson s attempt (problem 6 of book) public void wanttoentercs(int i) { // preprotocol last = i; desirecs[i].value = true; while (desirecs[other(i)].value && last == i) public void finishedincs(int I) { // postprotocol desirecs[i].value=false; page 23 page 24
Works for only two threads Note that if there are other threads doing other things, the yield() loop may not give control to the other thread dealing with this critical section. Have to hope that sooner or later the other contending thread gets a chance to do its preprotocol. page 25