How to get the Race condition among multiple threads and how to handle using wait/notify (inter thread communication)
package com.rafi.concurrency;
public class RaceConditionTest2 {
public volatile Object locker1 = new Object();
public volatile Object locker2 = new Object();
public volatile Object locker3 = new Object();
public volatile boolean waitLock3 = false;
public volatile boolean waitLock2 = false;
public volatile boolean waitLock1 = false;
public class MyRunnable2 implements Runnable {
public void run() {
System.out.println( "MyRunnable2 started" );
synchronized( locker3 ) {
try {
System.out.println( "r2: waiting for locker3" );
waitLock3 = true;
locker3.wait();
System.out.println( "r2: got locker3" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
for ( int c = 0; c < 2; ++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 < 2; ++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) {
RaceConditionTest t = new RaceConditionTest();
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 ) {
}*/
while(!waitLock3){
synchronized( locker3 ) {
System.out.println( "main: signaling locker3" );
locker3.notifyAll();
// locker3.notify();
waitLock3 = false;
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 );
}
}
}
The above code contains the race conditions between three threads. At some unlucky time the One of the threads wait indefinitely when nobody is there to notify.
To avoid java.lang.IllegalMonitorStateException, first acquire lock on the object using synchronized keyword
Here are points that Brian emphasized:
package com.rafi.concurrency;
public class RaceConditionTest2 {
public volatile Object locker1 = new Object();
public volatile Object locker2 = new Object();
public volatile Object locker3 = new Object();
public volatile boolean waitLock3 = false;
public volatile boolean waitLock2 = false;
public volatile boolean waitLock1 = false;
public class MyRunnable2 implements Runnable {
public void run() {
System.out.println( "MyRunnable2 started" );
synchronized( locker3 ) {
try {
System.out.println( "r2: waiting for locker3" );
waitLock3 = true;
locker3.wait();
System.out.println( "r2: got locker3" );
} catch ( java.lang.InterruptedException e ) {
System.out.println( "e: " + e );
}
}
for ( int c = 0; c < 2; ++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 < 2; ++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) {
RaceConditionTest t = new RaceConditionTest();
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 ) {
}*/
while(!waitLock3){
synchronized( locker3 ) {
System.out.println( "main: signaling locker3" );
locker3.notifyAll();
// locker3.notify();
waitLock3 = false;
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 );
}
}
}
The above code contains the race conditions between three threads. At some unlucky time the One of the threads wait indefinitely when nobody is there to notify.
To avoid java.lang.IllegalMonitorStateException, first acquire lock on the object using synchronized keyword
Here are points that Brian emphasized:
- If you read or write a field that is read/written by another thread, you must synchronize. This must be done by both the reading and writing threads, and on the same lock.
- Don't try to reason about ordering in undersynchronized programs.
- Avoiding synchronization can cause subtle bugs that only blow up in production. Do it right first, then make it fast.
No comments:
Post a Comment