I'm trying to remember my old CS days.
Been trying to properly implement, with the lowest possible primitives, a pair of synchronized threads. Of course I should use better concurrency tools on production code (stuff from java.util.concurrency, probably). But hey, I'm doing this for the challenge. Here is my code (this is my first question, so if this is much too long, please forgive me):
public class Test {
public volatile Object locker1 = new Object();
public volatile Object locker2 = new Object();
public volatile Object locker3 = new Object();
public class MyRunnable2 implements Runnable {
public void run() {
System.out.println( "MyRunnable2 started" );
synchronized( locker3 ) {
try {
System.out.println( "r2: waiting for locker3" );
locker3.wait();
System.out.println( "r2: got locker3" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
for ( int c = 0; c < 50; ++c ) {
synchronized( locker2 ) {
try {
System.out.println( "r2: waiting for locker2" );
locker2.wait();
System.out.println( "r2: got locker2" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
System.out.println( "r2: " + ( c ) );
try {
Thread.sleep(1);
} catch ( Exception e ) {
}
synchronized( locker1 ) {
System.out.println( "r2: signaling locker1" );
locker1.notify();
System.out.println( "r2: locker1 signaled" );
}
}
}
}
public class MyRunnable1 implements Runnable {
public void run() {
System.out.println( "MyRunnable1 started" );
synchronized( locker3 ) {
try {
System.out.println( "r1: waiting for locker3" );
locker3.wait();
System.out.println( "r1: got locker3" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
for ( int c = 0; c < 50; ++c ) {
synchronized( locker1 ) {
try {
System.out.println( "r1: waiting for locker1" );
locker1.wait();
System.out.println( "r1: got locker1" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
System.out.println( "r1: " + ( c ) );
try {
Thread.sleep(1);
} catch ( Exception e ) {
}
synchronized( locker2 ) {
System.out.println( "r1: signaling locker2" );
locker2.notify();
System.out.println( "r1: locker2 signaled" );
}
}
}
}
public static void main(String[] args) {
Test t = new Test();
t.test();
}
public void test() {
MyRunnable1 r1 = new MyRunnable1();
MyRunnable2 r2 = new MyRunnable2();
Thread t1 = new Thread( r1 );
Thread t2 = new Thread( r2 );
t1.start();
t2.start();
try {
Thread.sleep(1000);
} catch ( Exception e ) {
}
synchronized( locker3 ) {
System.out.println( "main: signaling locker3" );
locker3.notifyAll();
System.out.println( "main: locker3 signaled" );
}
try {
Thread.sleep(1000);
} catch ( Exception e ) {
}
synchronized( locker1 ) {
System.out.println( "main: signaling locker1" );
locker1.notify();
System.out.println( "main: locker1 signaled" );
}
try {
t1.join();
t2.join();
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
}
My question is: How can I avoid the race condition at Test.test()? Most of the time, this works - but I'm not satisfied with the sleep call. Also, please, I ask you people to evaluate my style. I'm always open to self-improvement.
EDIT: Just to make it clearer. I want MyRunnable1 to always run first. Print a number and then wait for MyRunnable2 to print the same number. Then it would print a second number and then wait for MyRunnable2 again. And so on.
I guess I can't comfortably use java.util.concurrency until I know what happens under the hood.