import java.awt.*; import java.awt.event.*; import javax.swing.*; // Functionally equivalent to Deadly5 // Synchronized code moved to Counter class public class Deadly6 extends JFrame implements ActionListener { private JTextField numField, counterField, statusField; private JButton start, stop; private Counter c; private CountThread c1, c2; public Deadly6() { setTitle("Race Condition"); setSize(500, 100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container pane = getContentPane(); pane.setLayout(new FlowLayout()); numField = new JTextField(10); pane.add(numField); start = new JButton("Start Counters"); start.addActionListener(this); pane.add(start); stop = new JButton("Stop"); stop.addActionListener(this); pane.add(stop); statusField = new JTextField(10); pane.add(statusField); counterField = new JTextField(20); pane.add(counterField); c = new Counter(); c1 = c2 = null; } public void actionPerformed(ActionEvent e) { if (e.getSource() == start && c1 == null && c2 == null) { int n = Integer.parseInt(numField.getText()); c1 = new CountThread(c, 1, n); c2 = new CountThread(c, -1, n); c1.start(); c2.start(); statusField.setText("running..."); } else if (e.getSource() == stop) { if (c1 != null) {c1.interrupt();} if (c2 != null) {c2.interrupt();} statusField.setText("interrupted"); } } public void done(CountThread d) { if (d == c1) {c1 = null;} else {c2 = null;} if (c1 == null && c2 == null) { statusField.setText("Finished"); } } class Counter { private long x = 0; public long getX() {return x;} synchronized public void increaseX(long incr) throws InterruptedException { while (x < 0 && incr < 0) {wait();} x = x + incr; counterField.setText(Long.toString(x)); notifyAll(); } public String toString() {return "Count: " + x;} } class CountThread extends Thread { private long incr, total; private Counter counter; public CountThread(Counter c, long i, long n) { counter = c; incr = i; total = n; } public void run() { long i = 0; try { while (!isInterrupted() && i < total) { counter.increaseX(incr); ++i; } System.out.println("Finished " + i + " loops"); } catch (InterruptedException ie) { System.out.println("Interrupted at loop " + i); } finally { done(this); } } } public static void main(String[] args) { Deadly6 f = new Deadly6(); f.setVisible(true); } }