/* * This example shows that Java wait/notify use the `signal and continue' * signaling discipline. One may generate multiple signals inside a * monitor and continue executing inside the monitor until a return. * IMPORTANT NOTE: it is possible that a signaled thread may not resume * inside the monitor until after another thread that was blocked on a * method call enters and leaves (or waits inside) the monitor. This * can be seen happening in the sample output shown below. Sleeper 3 * gets in the monitor before Sleepers 1 and 2 proceed after being * signaled. This is an example of "barging." Caveat programmer! * * Also note that the Windows 95 sample run shows the Sleeper threads * waking up after being signaled and proceeding in the monitor in the * opposite order that they queued up on the condition variable. In * contrast, the Solaris sample run shows FIFO queueing and wakeup on * the condition variable. But FIFO is not guaranteed! */ import Utilities.*; class DriverShowSigDis extends MyObject { private static Thread[] sleeperThread = null; private static Thread wakerThread = null; private static MonitorShowSigDis mssd = null; public static void main(String[] arg) { mssd = new MonitorShowSigDis(); sleeperThread = new Thread[3]; for (int i = 0; i < 3; i++) sleeperThread[i] = new Thread(new SleeperThread(i+1, mssd)); wakerThread = new Thread(new WakerThread(9, mssd)); for (int i = 0; i < 3; i++) sleeperThread[i].start(); wakerThread.start(); nap(10000); System.exit(0); } } /* ............... Example compile and run(s) % javac sigd.java % java DriverShowSigDis Sleeper 1 wants to enter monitor gotoSleep method at time 1051 Thread 1 enters monitor gotoSleep method at time 1087 Thread 1 queues on c.v. gotoSleep method at time 1200 Sleeper 2 wants to enter monitor gotoSleep method at time 2049 Thread 2 enters monitor gotoSleep method at time 2058 Thread 2 queues on c.v. gotoSleep method at time 2169 Waker 9 wants to enter monitor wakeUp method at time 2559 Thread 9 enters monitor wakeUp method at time 2570 Sleeper 3 wants to enter monitor gotoSleep method at time 3059 Thread 9 signals c.v in wakeUp method at time 3580 Thread 9 continues in wakeUp method at time 3590 Thread 9 signal two! in wakeUp method at time 3700 Thread 9 leaves monitor wakeUp method at time 3819 Waker 9 done at time 3828 Thread 3 enters monitor gotoSleep method at time 3837 Thread 3 queues on c.v. gotoSleep method at time 3949 Thread 1 awakes on c.v. gotoSleep method at time 3958 Thread 1 leaves monitor gotoSleep method at time 4070 Sleeper 1 done at time 4081 Thread 2 awakes on c.v. gotoSleep method at time 4089 Thread 2 leaves monitor gotoSleep method at time 4199 Sleeper 2 done at time 4207 D:\>javac sigd.java D:\>java DriverShowSigDis Sleeper 1 wants to enter monitor gotoSleep method at time 1050 Thread 1 enters monitor gotoSleep method at time 1050 Thread 1 queues on c.v. gotoSleep method at time 1160 Sleeper 2 wants to enter monitor gotoSleep method at time 2040 Thread 2 enters monitor gotoSleep method at time 2040 Thread 2 queues on c.v. gotoSleep method at time 2150 Waker 9 wants to enter monitor wakeUp method at time 2530 Thread 9 enters monitor wakeUp method at time 2530 Sleeper 3 wants to enter monitor gotoSleep method at time 3030 Thread 9 signals c.v in wakeUp method at time 3570 Thread 9 continues in wakeUp method at time 3570 Thread 9 signal two! in wakeUp method at time 3680 Thread 9 leaves monitor wakeUp method at time 3790 Waker 9 done at time 3790 Thread 3 enters monitor gotoSleep method at time 3790 Thread 3 queues on c.v. gotoSleep method at time 3900 Thread 2 awakes on c.v. gotoSleep method at time 3900 Thread 2 leaves monitor gotoSleep method at time 4010 Sleeper 2 done at time 4010 Thread 1 awakes on c.v. gotoSleep method at time 4010 Thread 1 leaves monitor gotoSleep method at time 4120 Sleeper 1 done at time 4120 ... end of example run(s) */ class MonitorShowSigDis extends MyObject { public MonitorShowSigDis() {} public synchronized void gotoSleep(int id) { System.out.println ("Thread "+ id +" enters monitor gotoSleep method at time "+ age()); nap(100); System.out.println ("Thread "+ id +" queues on c.v. gotoSleep method at time "+ age()); try { wait(); } catch (InterruptedException e) { System.err.println("interrupted out of wait"); } System.out.println ("Thread "+ id +" awakes on c.v. gotoSleep method at time "+ age()); nap(100); System.out.println ("Thread "+ id +" leaves monitor gotoSleep method at time "+ age()); } public synchronized void wakeUp(int id) { System.out.println ("Thread "+ id +" enters monitor wakeUp method at time "+ age()); nap(1000); System.out.println ("Thread "+ id +" signals c.v in wakeUp method at time "+ age()); notify(); System.out.println ("Thread "+ id +" continues in wakeUp method at time "+ age()); nap(100); System.out.println ("Thread "+ id +" signal two! in wakeUp method at time "+ age()); notify(); nap(100); System.out.println ("Thread "+ id +" leaves monitor wakeUp method at time "+ age()); } } class SleeperThread extends MyObject implements Runnable { private int id = 0; private MonitorShowSigDis mssd = null; public SleeperThread(int id, MonitorShowSigDis mssd) { this.id = id; this.mssd = mssd; } public void run() { nap(id*1000); System.out.println("Sleeper "+ id +" wants to enter monitor gotoSleep method at time "+ age()); mssd.gotoSleep(id); System.out.println ("Sleeper "+ id +" done at time "+ age()); } } class WakerThread extends MyObject implements Runnable { private int id = 0; private MonitorShowSigDis mssd = null; public WakerThread(int id, MonitorShowSigDis mssd) { this.id = id; this.mssd = mssd; } public void run() { nap(2500); System.out.println ("Waker 9 wants to enter monitor wakeUp method at time "+ age()); mssd.wakeUp(9); System.out.println ("Waker 9 done at time "+ age()); } }