The Apprentice Challenge J Strother Moore Department of Computer Sciences University of Texas at Austin 1
A Class Involving Multiple Threads class Container { public int counter; } class Job extends Thread { Container objref; public void setref(Container o) { objref = o; } 2
public Job incr () { synchronized(objref) { objref.counter = objref.counter + 1; } return this; } public void run() { for (;;) { incr(); } } } 3
class Apprentice { public static void main(String[] args) { Container container = new Container(); for (;;) { Job job = new Job(); job.setref(container); job.start(); } } } 4
Theorem The value of the counter never decreases. This has to be formulated more carefully to account for Java’s 32-bit int arithmetic. 5
Theorem (let* ((s1 (run sched *a0*)) (s2 (step th s1))) (or (equal (counter s1) nil) (equal (counter s1) (counter s2)) (equal (int-fix (+ 1 (counter s1))) (counter s2)))) 6
It’s Obvious... class Container { public int counter; } class Job extends Thread { Container objref; public void setref(Container o) { objref = o; } public Job incr () { synchronized(objref) { objref.counter = objref.counter + 1; } return this; } public void run() { for (;;) { incr(); } } } class Apprentice { public static void main(String[] args) { Container container = new Container(); for (;;) { Job job = new Job(); job.setref(container); job.start(); } } } 7
class Container { public int counter; } class Job extends Thread { Container objref; public void setref(Container o) { objref = o; } public Job incr () { synchronized(objref) { objref.counter = objref.counter + 1; } return this; } public void run() { for (;;) { incr(); } } } class Apprentice { public static void main(String[] args) { Container container = new Container(); Container bogus = new Container(); for (;;) { Job job = new Job(); job.setref(bogus); job.start(); job.setref(container); } } } 8
Thread Table Class Table Thread 0 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Apprentice main() Container container = new Container(); Container bogus = new Container() for (;;) { Job job = new Job(); job.setref(bogus); job.start(); job.setref(container);} 9
Thread Table Class Table Thread 0 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Apprentice main() Container container = new Container(); container Container bogus = new Container() counter: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: −−− 10
Thread Table Class Table d e l �������� �������� u Thread 0 Thread 1 Job incr() d �������� �������� e �������� �������� synchronized(objref) h �������� �������� c {objref.counter = objref.counter + 1;} �������� �������� s n �������� �������� u �������� �������� Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: −−− 11
Thread Table Class Table d e l u �������� �������� Thread 0 Thread 1 d Job incr() �������� �������� e �������� �������� h synchronized(objref) �������� �������� c {objref.counter = objref.counter + 1;} s �������� �������� n �������� �������� u �������� �������� Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: −−− 12
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: −−− 13
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: −−− 14
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: Thread 1 15
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: Thread 1 16
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: Thread 1 17
Thread Table Class Table Thread 0 Thread 1 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Apprentice main() Container container = new Container(); container Job1 Container bogus = new Container() counter: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: Thread 1 18
Thread Table Class Table Thread 0 Thread 1 Thread 2 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Apprentice main() Container container = new Container(); container Job1 Job2 Container bogus = new Container() counter: objref: objref: for (;;) { Job job = new Job(); 0 job.setref(bogus); job.start(); monitor: job.setref(container);} −−− container counter: 0 monitor: Thread 1 19
Thread Table Class Table Thread 0 Thread 1 Thread 2 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Job incr() container Job1 Job2 synchronized(objref) {objref.counter = objref.counter + 1;} counter: objref: objref: 1000000 monitor: Thread 2 container counter: 0 monitor: Thread 1 20
Thread Table Class Table Thread 0 Thread 1 Thread 2 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} 1 Heap Job incr() container Job1 Job2 synchronized(objref) {objref.counter = objref.counter + 1;} counter: objref: objref: 1000000 monitor: Thread 2 container counter: 0 monitor: Thread 1 21
Thread Table Class Table Thread 0 Thread 1 Thread 2 Job incr() synchronized(objref) {objref.counter = objref.counter + 1;} Heap Job incr() container Job1 Job2 synchronized(objref) {objref.counter = objref.counter + 1;} counter: objref: objref: 1 1000000 monitor: Thread 2 container counter: 0 monitor: Thread 1 22
class Container { public int counter; } class Job extends Thread { Container objref; public void setref(Container o) { objref = o; } public Job incr () { synchronized(objref) { objref.counter = objref.counter + 1; } return this; } public void run() { for (;;) { incr(); } } } class Apprentice { public static void main(String[] args) { Container container = new Container(); for (;;) { Job job = new Job(); job.setref(container); job.start(); } } } 23
Theorem (let* ((s1 (run sched *a0*)) (s2 (step th s1))) (rel (counter s1) (counter s2))) 24
(defthm Lemma-1 (good-state *a0*)) (defthm Lemma-2 (implies (good-state s) (good-state (step th s)))) (defthm Lemma-3 (implies (good-state s) (rel (counter s) (counter (step th s))))) 25
Recommend
More recommend