昔の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 が同じ数値を出力するのを待ちます。次に、2 番目の数値を出力し、MyRunnable2 を再び待ちます。等々。
内部で何が起こっているかを知るまで、java.util.concurrency を快適に使用することはできないと思います。