Understanding Java Wait and Notify methods - java

I have a following program:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleWaitNotify implements Runnable {
final static Object obj = new Object();
static boolean value = true;
public synchronized void flag() {
System.out.println("Before Wait");
try {
obj.wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("After Being Notified");
}
public synchronized void unflag() {
System.out.println("Before Notify All");
obj.notifyAll();
System.out.println("After Notify All Method Call");
}
public void run() {
if (value) {
flag();
} else {
unflag();
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(4);
SimpleWaitNotify sWait = new SimpleWaitNotify();
pool.execute(sWait);
SimpleWaitNotify.value = false;
SimpleWaitNotify sNotify = new SimpleWaitNotify();
pool.execute(sNotify);
pool.shutdown();
}
}
When I wait on obj, I get the following exception Exception in thread "pool-1-thread-1" java.lang.IllegalMonitorStateException: current thread not owner for each of the two threads.
But if I use SimpleWaitNotify's monitor then the program execution is suspended. In other words, I think it suspends current execution thread and in turn the executor. Any help towards understanding what's going on would be duly appreciated.
This is an area1 where the theory and javadoc seem straightforward, and since there aren't many examples, conceptually left a big gap in me.

You're calling wait and notifyAll on obj, but you're synchronizing on this (because you've got synchronized methods).
In order to wait or notify, you need to "own" the monitor first. Unsynchronize the methods, and synchronize on obj instead:
public void flag() {
System.out.println("Before Wait");
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
System.out.println("After Being Notified");
}
public void unflag() {
System.out.println("Before Notify All");
synchronized (obj) {
obj.notifyAll();
}
System.out.println("After Notify All Method Call");
}

Either synchronize on obj, or call wait and notify on this. The calling thread must hold the monitor of the same object on which these methods are called.
For example,
synchronized void flag() {
System.out.println("Before Wait");
try {
wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("After Being Notified");
}
In this example, the lock is held on this (when the modifier synchronized is used on a instance method, the monitor of the instance is acquired). So, the wait() method may be invoked on the implied instance this.
In order to coordinate the two threads, they need to share the same lock. The original version had a static obj that could be used as a lock, but it wasn't used in the synchronized blocks. Here is a better example:
class SimpleWaitNotify implements Runnable {
private final Object lock;
private final boolean wait;
SimpleWaitNotify(Object lock, boolean wait) {
this.lock = lock;
this.wait = wait;
}
public void flag() {
synchronized (lock) {
System.out.println("Before Wait");
try {
lock.wait();
System.out.println("After Being Notified");
} catch (InterruptedException ex) {
System.out.println("Thread interrupted");
}
}
}
public void unflag() {
synchronized(lock) {
System.out.println("Before Notify All");
lock.notifyAll();
System.out.println("After Notify All Method Call");
}
}
public void run() {
if (wait) {
flag();
} else {
unflag();
}
}
public static void main(String[] argv) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(4);
Object shared = new Object();
SimpleWaitNotify sWait = new SimpleWaitNotify(shared, true);
pool.execute(sWait);
SimpleWaitNotify sNotify = new SimpleWaitNotify(shared, false);
pool.execute(sNotify);
pool.shutdown();
}
}

Rather putting the direct statement pool.shutdown(), try as below.
while (!service.isTerminated())
{
service.shutdown();
}
So it will wait for till all the threads execution completes.

Related

Threads stopped print characters and all of them are waiting for lock

I want to use 3 threads to print A、B、C randomly,so I wrote code as below:
public class ThreadPrint4Test {
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
}
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A",lock),"thread-A").start();
new Thread(new PrintThread("B",lock),"thread-B").start();
new Thread(new PrintThread("C",lock),"thread-C").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (lock) {
lock.notifyAll();
}
}).start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
}
public void run() {
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
But when I test the program,it stoppted print characters after a few seconds
Using jps and jstack I found all the 3 threads are WAITING the object lock
I tested it for serveral times,and this phenomenon occurs every time.
I do not know why all the 3 threads are waiting object lock at same time
Based on my knowledge,each time one of the 3 threads will be awake and have the chance to exeute,then it will awake all the 3 threads randomly by invoking lock.notifyAll();. So the program should run continuous theoretically,But now each time I test it,it will stop print characters after a few seconds.
Could someone help analysis why this happen? Thanks in advance!
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Your problem is that you are calling notifyAll() immediately after calling wait(). You get to a deadlock situation where each thread is waiting. When all the threads are waiting, none of them can be notified, hence your program comes to a standstill.
According to the Concurrency tutorial, you need to wait() for a certain condition to occur. Once the condition occurs, you perform the required action (which, in your code, is printing the current time) then you call notifyAll() to inform the waiting threads that you have completed performing the required action and that they can try to perform their required action.
Explanations after the code.
import java.time.LocalTime;
public class ThreadPrint4Test {
private volatile boolean canPrint;
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A", lock), "thread-A").start();
new Thread(new PrintThread("B", lock), "thread-B").start();
new Thread(new PrintThread("C", lock), "thread-C").start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
canPrint = true;
}
public void run() {
while (true) {
while (!canPrint) {
try {
synchronized (lock) {
System.out.printf("[%s] Waiting...%n", value);
lock.wait();
}
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
synchronized (lock) {
canPrint = false;
System.out.println(LocalTime.now() + "\t" + value);
canPrint = true;
lock.notifyAll();
}
}
}
}
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
try {
Thread.sleep(2000);
}
catch (InterruptedException x) {
x.printStackTrace();
}
System.exit(0);
}
}
I added a canPrint flag. When it is true, then the thread can print the current time. When it is false, the thread must wait.
When the thread can print the current time, it first sets the flag to false so that no other thread can print.
After the thread has printed the current time, it sets the flag back to true and calls method notifyAll() which causes all waiting threads to stop waiting and re-check the canPrint flag.
The first thread to awake after canPrint has been set to true, sets the flag to false which causes all other threads to wait.

Skipping a method when it is already executed by another thread

My question is related to this one: Exit a method if another thread is executing it
There is a method which is is executed by multiple threads. If one thread is executing the method any other thread should just exit. My solution is like this:
public class ReentrantLockTest implements Runnable {
private static final ReentrantLock LOCK = new ReentrantLock();
#Override
public void run() {
if (LOCK.tryLock()) {
System.out.println("Aquired. Thread " + Thread.currentThread().getId());
try {
// do stuff here
} catch (Exception e) {
// handle errors
} finally {
// release the lock
LOCK.unlock();
}
}
}
This seems fine to me but in production it sometimes happens that the lock remains unreleased thus the method is not getting executed at all unless I restart the system.
So I have two questions:
1. How is it possible that the lock doesn't get released?
2. What is a good way of testing such code? Just running this in a loop and hope it'll crash at some point if there's a bug doesn't seem like a good solution.
You should use the synchronised keyword. This ensures that only one thread executes a block of code at the same time.
Change your method to:
public synchronised void run() {
//your code
}
package thread;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ReentrantLockTest implements Runnable
{
private static final ReentrantLock LOCK = new ReentrantLock();
#Override
public void run()
{
boolean done = false;
while (!done)
{
boolean ans=LOCK.tryLock();
if(ans)
{
System.out.println("Aquired. Thread " + Thread.currentThread().getId());
try {
// do stuff here
System.out.println(Thread.currentThread().getName()+ " in try block");
done = true;
}catch (Exception e) {
// handle errors
} finally {
// release the lock
LOCK.unlock();
System.out.println(Thread.currentThread().getName()+" unlock");
}
}
else
{
System.out.println(Thread.currentThread().getName() + " waiting for lock");
try
{Thread.sleep(1000);}
catch(InterruptedException e)
{e.printStackTrace();}
}
}
}
}
public class ReentrantLockDemo2
{
public static void main(String[] args)
{
ExecutorService pool=Executors.newFixedThreadPool(5);
Runnable t1=new ReentrantLockTest();
Runnable t2=new ReentrantLockTest();
Runnable t3=new ReentrantLockTest();
Runnable t4=new ReentrantLockTest();
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.shutdown();
System.out.println("Main Close");
}
}

What can cause IllegalMonitorStateException in the given sample code

I am trying to learn java concurrency programming. Kindly check my sample code and help me understanding why I'm getting "java.lang.IllegalMonitorStateException" even though I have called wait() and notify in a synchronized context.
public class Test {
public static void main(String[] args) throws Exception {
Test t1 = new Test();
t1.m1();
}
private void m1() {
Example ex = new Example();
Thread t1 = new Thread(ex);
t1.start();
synchronized (ex) {
System.out.println("waiting");
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Example implements Runnable {
#Override
public void run() {
System.out.println("Running");
notifyMethod();
}
private void notifyMethod() {
System.out.println("Notifying");
synchronized (this) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
notify();
}
}
}
}
I expect out of "waiting,running,notifying" but the actual output is:
waiting
Running
java.lang.IllegalMonitorStateException
Notifying
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at examples.Test.m1(Test.java:18)
at examples.Test.main(Test.java:8)
First of, I think synchonizing on a Runnable isn't a good idea (Example in your case). You either synchonize on this or, even better, on a dedicated Object, that is lock in my example. Edit: Synchronizing on a Runnable is the same as using this but for me it looks better. Guts tell me there might be something more to that, but I'm not an expert in this field. Dedicated lock Object is always better, read this article if you want to find out more on the topic.
Then, while synchonizing on a lock, you have to call wait() on that same object: lock.wait(). If you synchronize on this, then you call this.wait() or just wait().
When you want to notify the waiting thread, you again have to synchronize on the lock and call notify() on that object: lock.notify(). Both the monitor in the synchronize and the object on which you call notify() have to be the exact same object you have called wait() on.
Here is a code that works:
public class Test {
public static final Object lock = new Object();
public static void main(String[] args) throws Exception {
Test t1 = new Test();
t1.m1();
}
private void m1() {
Example ex = new Example();
Thread t1 = new Thread(ex);
t1.start();
synchronized (lock) {
System.out.println("waiting");
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class Example implements Runnable {
#Override
public void run() {
System.out.println("Running");
notifyMethod();
}
private void notifyMethod() {
System.out.println("Notifying");
synchronized (lock) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
lock.notify();
}
}
}
}

Trying to create a deadlock between two threads

For creating a deadlock in between two threads by accessing print method into Threads. I have used cyclic Barrier so that both of the thread starts at same time. If I am correct my print method is not taking time, for that reason it is getting shared by the two threads and not causing a Deadlock.
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class TWOTHREADDEADLOCLK {
static int b =0;
synchronized static void print()
{
System.out.println(Thread.currentThread().getName() + " " + b);
}
synchronized static int getb()
{
print();
return b;
}
synchronized static void updateb()
{
print();
b=b+10;
}
public static void main(String[] args) {
final CyclicBarrier bar = new CyclicBarrier(2);
Thread thread1 = new Thread(new Runnable(){
#Override
public void run()
{
try {
bar.await();
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch ( BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
while(true)
print();
}
});
Thread thread2 = new Thread(new Runnable(){
#Override
public void run()
{try {
bar.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
while(true)
getb();
}
});
thread1.start();
thread2.start();
}
}
You can't create a deadlock with a single barrier. The idea behind a deadlock is to have (at least) two threads, each one holding a different lock and attempting to take a lock on the other one. E.g., consider this simple example:
public class TwoLockRunnable implements Runnable {
private Lock lockInConstructor;
private Lock lockInRuntime;
public TwoLockThread(Lock lockInConstructor, Lock lockInRuntime) {
this.lockInConstructor = lockInConstructor;
this.lockInRuntime = lockInRuntime;
this.lockInConstructor.lock();
}
#Override
public void run() {
lockInRuntime.lock();
System.out.println("After the lock in run()");
}
public static void main(String[] args) {
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
TwoLockRunnable runnable1 = new TwoLockThread(lock1, lock2);
TwoLockRunnable runnable2 = new TwoLockThread(lock2, lock1);
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}
The first thread locks lock1 in its constructor and the second locks lock2 in its constructor. The first thread then tries to lock lock2 when its run - but it can't since lock is held by the other thread. Similarly, the second thread attempts to lock lock1 when its run, and fails for the same reason. Thus, you get a deadlock, and the message "After the lock in run()" is never printed.
like Mureinik's, this is the 'synchronized' demo:
public class DeadLockAATest {
static void methodA(DeadLockAATest d1, DeadLockAATest d2) {
synchronized (d1) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (d2) {
System.out.println("\t\t\tmethodA:" + Thread.currentThread().getName());
}
}
}
public static void main(String[] args) {
DeadLockAATest d1 = new DeadLockAATest(), d2 = new DeadLockAATest();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("t1-start:" + Thread.currentThread().getName());
methodA(d1, d2);
System.out.println("t1-end:" + Thread.currentThread().getName());
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("t2-start:" + Thread.currentThread().getName());
methodA(d2, d1);
System.out.println("t2-end:" + Thread.currentThread().getName());
}
});
t1.start();
t2.start();
System.out.println("deadlock...");
}
}
the deadlock output(just one contion, maybe t2 starts first):
t1-start:Thread-0
deadlock...
t2-start:Thread-1
you can replace
methodA(d2, d1);
to
methodA(d1, d2);
and this will output:
t1-start:Thread-0
t2-start:Thread-1
deadlock...
methodA:Thread-0
t1-end:Thread-0
methodA:Thread-1
t2-end:Thread-1
and this is not deadlock, hope to help you.

Having troubles with threads and semaphors in JAVA

I am new to threading and semaphors, and I have some problem in synchronizing threads. For example, in the following code I want to do a pretty simple thing. To let one thread run, while other waits. For example, if it starts with the first thread, I want the second to wait for the first one to finish and then start. I really don't know what am I doing wrong.
Here is the code :
import java.io.*;
import java.util.concurrent.Semaphore;
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Semaphore binaren = new Semaphore(1);
Runnable t1 = new T2(binaren);
Thread a = new Thread(t1);
Thread a2 = new T1(binaren);
System.out.println(binaren.availablePermits());
a.start();
a2.start();
}
}
class Work {
private static int a = 4;
public synchronized static void QQR(String s1)
{
for(int i=0;i<100;i++)
System.out.println(s1+" : "+(a++));
}
}
class T1 extends Thread
{
Semaphore sem;
public T1(Semaphore s1)
{
sem=s1;
}
public void run()
{
synchronized(this) {
if(!sem.tryAcquire()){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Work.QQR("T1");
sem.release();
notifyAll();
}
}
}
class T2 extends Thread
{
Semaphore sem;
public T2(Semaphore s1)
{
sem=s1;
}
#Override
public void run() {
synchronized(this) {
if(!sem.tryAcquire()){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Work.QQR("T2");
sem.release();
notifyAll();
}
}
}
The problem is that notify and notifyAll only wake up threads holding locks on the monitor being notified. But the t1 and t2 instances are waiting on themselves and are never awoken. You can have them wait on the semaphore for this simple test or introduce a new shared object to see how it works.
Use
sem.wait();
and
sem.notifyAll();
You can use Thread.join() on the first thread so that second thread will wait till the execution of this instance is not completed.

Categories