From ExtremeProgrammingChallengeFourteenTheBug
import java.util.*;
public class BoundedBuffer {
synchronized void put(Object x) throws InterruptedException { while ( occupied == buffer.length ) { wait(); } /***/ TestBB.doSleep(); notify(); /***/ TestBB.doSleep(); ++occupied; putAt %= buffer.length; buffer[putAt++] = x; } synchronized Object take() throws InterruptedException { while ( occupied == 0 ) { wait(); } /***/ TestBB.doSleep(); notify(); --occupied; takeAt %= buffer.length; return buffer[takeAt++]; } private Object[] buffer = new Object[1]; private int putAt, takeAt, occupied;}
class TestBB extends Thread {
private static final int slow = 10; private static int[]c1sleeps = {0,slow}; private static int[]c2sleeps = {0,0}; private static int[]p1sleeps = {0,slow*2,slow*2}; private static int[]p2sleeps = {0,0,0}; private static BoundedBuffertheBB = new BoundedBuffer(); private static Hashtablethreads = new Hashtable(); public static void main(String[] args) throws Throwable { int pass = 0; int fail = 0; for (int i=0; i< 50; i++) { if (doTest()) { System.out.println("Fail."); fail++; } else { System.out.println("Pass."); pass++; } } System.out.println("Slow is "+slow+", false pass:"+pass+", fail:"+fail); } public static boolean doTest() throws Throwable { theBB = new BoundedBuffer(); c1sleeps[0] = 0; c2sleeps[0] = 0; p1sleeps[0] = 0; p2sleeps[0] = 0; TestBB c1 = new TestBB("c1",c1sleeps) { public void run() { try { theBB.take(); } catch (InterruptedException ie) {} } }; TestBB c2 = new TestBB("c2",c2sleeps) { public void run() { try { theBB.take(); } catch (InterruptedException ie) {} } }; TestBB p1 = new TestBB("p1",p1sleeps) { public void run() { try { theBB.put("A"); } catch (InterruptedException ie) {} } }; TestBB p2 = new TestBB("p2",p2sleeps) { public void run() { try { theBB.put("B"); } catch (InterruptedException ie) {} } }; c1.start(); Thread.sleep(slow); c2.start(); Thread.sleep(slow); p1.start(); Thread.sleep(slow); p2.start(); Thread.sleep(300+(slow*10)); if (p2.isAlive()) { System.out.println("Liveness problem detected."); return true; } else return false; } public TestBB(String name,int[] sleeps) { super(name); threads.put(this,sleeps); } public static void doSleep() { int[] sleepsForThread = (int[])threads.get(Thread.currentThread()); if (sleepsForThread != null) { int current = 1+(sleepsForThread[0] % (sleepsForThread.length-1)); sleepsForThread[0]++; try { Thread.sleep(sleepsForThread[current]); } catch(InterruptedException ie) {} } }}