我试图记住我以前的 CS 日子。
一直在尝试以尽可能低的原语正确实现一对同步线程。当然,我应该在生产代码上使用更好的并发工具(可能来自 java.util.concurrency 的东西)。但是,嘿,我这样做是为了挑战。这是我的代码(这是我的第一个问题,所以如果这太长了,请原谅我):
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 );
}
}
}
我的问题是:如何避免 Test.test() 的竞争条件?大多数情况下,这是可行的——但我对睡眠电话不满意。另外,请大家评价一下我的风格。我总是乐于自我提升。
编辑:只是为了让它更清楚。我希望 MyRunnable1 始终先运行。打印一个数字,然后等待 MyRunnable2 打印相同的数字。然后它会打印第二个数字,然后再次等待 MyRunnable2。等等。
我想我不能舒适地使用 java.util.concurrency 直到我知道引擎盖下发生了什么。