I'm trying to have a Thread2 wait for a String and Thread1 to notify on String update, I do synchronize The String object as code below shows, But I still get IllegalMonitorStateException Here's my code
public class Class1{
String string = "";
public Class1(){
Thread t1 = new Thread(){
public void run(){
synchronized(string){
string = "Something"; string.notifyAll(); //This is the line that throws an IllegalMonitorStateException
}
}
};
Thread t2 = new Thread(){
public void run(){
synchronized(string){
try{
string.wait();
}catch(Exception e){
e.printStackTrace();
}
}
}
};
t2.start();
t1.start();
}
}
There's nothing in StackTrace except highlighting string.notifyAll()
Your code contains a data race because it accesses the mutable string variable outside of a synchronized block. Specifically, this happens on the line synchronized(string). While dereferencing string to reach the object whose monitor will be locked, the thread does not already hold a lock on that object. Therefore you have no guarantee which object it will acquire a lock on.
The fact that you mutate the string variable means that it now points to some other object. When the next thread acquires a lock on that new object, it will not benefit from any happens-before relationship because it is the first thread to ever acquire a lock on it. Mutual exclusion will not be guaranteed, either, because there may be arbitrarily many threads, each locking a different String instance without contention.
Combining the two phenomena described above we can also see that there is no guarantee that the object reached on the line synchronized(string) will be the same one as the one reached from within the synchronized block. Once it happens that this is indeed a different object, your IllegalMonitorStateException ensues.
In summary, the situation is very similar to the synchronized block not existing at all.
All of the above problems can be avoided if you keep to the best practice of using dedicated final variables to refer to objects used for locking. In a nutshell, and fixing the compilation errors in your example, this is what you would have to write:
static String string = "";
static final Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
synchronized (lock) {
... update the string variable ...
lock.notifyAll();
}
}
};
Thread t2 = new Thread() {
public void run() {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
t2.start();
t1.start();
}
Related
In my Java program, I will launch two Threads simultaneously. I want for my program to join() on either one of two threads's completion without waiting for both threads to complete. In other words, if thread A finishes before thread B, I want the main thread to join thread A and resume the main thread without waiting for Thread B to finish and vice versa.
Which of those Java classes that allows me to do this?
One solution to accomplish that is with a CountDownLatch, by having the main thread wait for its count to reach zero, and having the two threads each decrease the count (the initial value of the count would be 1 in this case).
public static void main(String[] atrgs){
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
t1.start();
t2.start();
while(t1.isAlive()&&t2.isAlive()){
}
System.out.println("main resumes");
}
Actually, any class in Java allows you to do that since an object of any class can be used as a monitor for waiting a notification. Just create an object, call wait() on it and make your threads notify on this object when finished:
private class Foo implements Runnable {
private final int id;
private final Object monitor;
public Foo(int id, Object monitor) {
this.id = id;
this.monitor = monitor;
}
#Override
public void run() {
try {
Thread.sleep((long)(Math.random() * 10000));
} catch (InterruptedException e) {
}
System.out.println(id + " finished");
synchronized (monitor) {
monitor.notify();
}
}
}
public static void main(String[] args) throws InterruptedException {
final Object monitor = new Object();
synchronized (monitor) {
new Thread(new Foo(1, monitor)).start();
new Thread(new Foo(2, monitor)).start();
System.out.println("Main goes to sleep");
monitor.wait();
}
System.out.println("Main is running");
}
The first notification will unblock the main thread and it will continue running.
I would say that this is a classic solution for your problem, though the solution that #AR.3 suggested will be less wordy and will surely work. I just wanted to show that even a simple monitor object is enough to do what you want.
class Demo
{
void demo()
{
System.out.println("Inside demo of "+Thread.currentThread().getName());
try
{
Thread.sleep(1000000);
}
catch(InterruptedException exc)
{
System.out.println(Thread.currentThread().getName()+" interrupted");
}
}
}
class MyThread1 implements Runnable
{
Thread thread;
Demo d;
MyThread1(String name, Demo ob)
{
d = ob;
thread = new Thread(this, name);
thread.start();
}
#Override
public void run()
{
System.out.println(thread.getName()+" starting");
synchronized(d)
{
d.demo();
}
System.out.println(thread.getName()+" ending");
}
}
class MyThread2 implements Runnable
{
Thread thread;
Demo d;
MyThread2(String name, Demo ob)
{
d = ob;
thread = new Thread(this, name);
thread.start();
}
#Override
public void run()
{
System.out.println(thread.getName()+" starting");
d.demo();
System.out.println(thread.getName()+" ending");
}
}
class TimePass
{
public static void main(String args[])
{
Demo d = new Demo();
MyThread1 mt1 = new MyThread1("Thread 1", d);
MyThread2 mt2 = new MyThread2("Thread 2", d);
}
}
The output is
Thread 1 starting
Inside demo of Thread 1
Thread 2 starting
Inside demo of Thread 2
Due to Thread.sleep(1000000), the execution is not yet ended.
I have passed the same instance of class Demo to both the constructors of classes MyThread1 and MyThread2.
Demo d = new Demo();
MyThread1 mt1 = new MyThread1("Thread 1", d);
MyThread2 mt2 = new MyThread2("Thread 2", d);
The call to d.demo in MyThread1 is in a synchronized block.
The call to d.demo in MyThread2 is not in a synchronized block.
So, when MyThread1 is executing, due to the synchronized block, the monitor of d should be locked, resulting in denial of access to d.demo() by the MyThread2.
But this is not happening.
The expected output is
Thread 1 starting
Inside demo of Thread1
Thread 2 starting
(The output is before Thread.sleep(1000000) is finished.)
So, my basic question is: How MyThread2.d.demo() is executing successfully even if MyThread1.d.demo() is not yet finished the synchronized block?
So, when MyThread1 is executing, due to the synchronized block, the monitor of d should be locked, resulting in denial of access to d.demo() by the MyThread2.
That would only happen if MyThread2 also had a synchronized block. When one thread is synchronized on an object, other threads will be blocked if they also try to synchronize on that same object. If they don't synchronize, they won't be. There's nothing that stops access to an object from threads that don't synchronize on it.
Synchronization is a cooperative mechanism. It only works when all threads work together.
The synchronization only occurs in Thread1. Since Thread2 does not synchronize on d, it is allowed to invoke demo() while Thread1 holds the lock.
You seem to be misunderstanding the use of synchronized. Synchronization only occurs with other threads trying to enter a synchronized block of the common object.
Synchronization is a collaborative effort. Each party states that when another party is in a critical section, they won't be.
You've only synchronized access to the demo method of the Demo instance in one thread
synchronized(d)
{
d.demo();
}
The other is accessing it directly
d.demo();
They've broken these collaboration rules so you can't assume anything.
This is explained in the JLS
Acquiring the lock associated with an object does not in itself
prevent other threads from accessing fields of the object or invoking
un-synchronized methods on the object. Other threads can also use
synchronized methods or the synchronized statement in a conventional
manner to achieve mutual exclusion.
I am trying to understand how deadlocks are created. I've understood that by using two threads on two synchronized methods, a deadlock can be created.
Went through many examples from the net.
Can a deadlock be created with wait and notify?
Every time a thread is on wait, it will be notified. So how does this end up in a deadlock?
Illustration of an example will be helpful.
Deadlock is caused when two threads try to obtain the same, multiple locks in different order:
// T1
synchronized (A) {
synchronized (B) {
// ...
}
}
// T2
synchronized (B) {
synchronized (A) {
// ...
}
}
The only way to prevent deadlocks is to make sure that all threads obtain locks in the same order--either they all do A then B, or they all do B then A.
If you don't have multiple locks, then you don't have a deadlock. However, you can get thread starvation or other things that may look similar to deadlock.
Say thread 1 enters a synchronized block on method A and then waits. Thread 2 then attempts to enter the synchronized block on method A. Thread 1 is waiting for a notify, and thread 2 is waiting on the synchronized block. Everything is now waiting. Some other thread will have to notify the object on which thread 1 is waiting. This is just one scenario that can create a deadlock. There are all kinds of ways to do it.
A thread which is on wait will not be notified unless some code explicitly notifies it. Therefore the example you are looking for is absolutely trivial:
public static void main(String[] args) {
synchronized(String.class) {
String.class.wait();
}
}
and this hangs forever. Technically, though, it is not a deadlock, which requires two or more threads involved in a closed cycle where each thread waits for the next one to unblock it.
Something close to wait/notify deadlock:
public class Example
{
volatile boolean isNotified = false;
public synchronized void method1() {
try
{
isNotified = false;
while (!isNotified)
wait();
notifyAll();
System.out.println("Method 1");
} catch (InterruptedException e) {/*NOP*/}
}
public synchronized void method2() {
try {
isNotified = true;
while (isNotified)
wait();
notifyAll();
System.out.println("Method 2");
} catch (InterruptedException e) {/*NOP*/}
}
public static void main(String[] args)
{
Example example = new Example();
Thread thread1 = new Thread()
{
public void run()
{
example.method1();
}
};
Thread thread2 = new Thread()
{
public void run()
{
example.method2();
}
};
thread1.start();
thread2.start();
}
}
This question already has answers here:
Synchronizing on an object in java, then changing the value of the synchronized-on variable
(4 answers)
Closed 5 years ago.
private volatile Object obj = new MyObject();
void foo()
{
synchronized(obj)
{
obj.doWork();
}
}
void bar()
{
synchronized(obj)
{
obj.doWork();
obj = new MyObject(); // <<<< notice this line (call it line-x)
}
}
Suppose at a certain point in time, a thread t_bar is executing bar(), and another one t_foo is executing foo, and that t_bar has just acquired obj, so t_foo is, in effect, waiting.
After the sync-block in bar is executed, foo will get to execute its sync-block, right? What value of obj would it see? The old one? Or the new one set in bar?
(I would hope that the new value is seen, that's the whole point of coding it that way, but I want to know if this is a 'safe' bet)
In the exact situation you described, yes, the read of obj inside foo's synchronized block will see the new value set by the previous bar's synchronized block.
The fun part is, it doesn't always happen in that exact situation. The program is not thread safe, for example, if immediately after bar() exits, the same threads invokes another bar(), while the foo thread is locking on the old object. The bar thread locks on the new object, so the two threads are executing concurrently, both executing obj.doWork() on the same new obj.
We can probably partially fix it by
// suppose this line happens-before foo()/bar() calls
MyObject obj = new MyObject();
void foo()
while(true)
MyObject tmp1 = obj;
synchronized(tmp1)
MyObject tmp2 = obj;
if(tmp2==tmp1)
tmp2.doWork();
return;
// else retry
this at least guarantees no current invocations of obj.doWork() on the same obj, since obj.doWork() can only occur in a synchronized block that locks the exact same obj
It will behave normally as if object reference was not changed internally. Reason being that test for lock on object will be done only once. So even if object changes internally, thread will keep waiting and behaviour will remian same as if object was same [unchanged].
I tried another thing. I placed a sleep statement just after new object was created and then started the next thread and as expected both threads started working simultaneously.
See the code below.
public class ChangeLockObjectState {
private volatile Object obj = new Object();
void foo() {
synchronized (obj) {
try {
System.out.println("inside foo");
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void bar() {
synchronized (obj) {
try {
System.out.println("inside bar");
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
obj = new Object(); // <<<< notice this line (call it line-x)
System.out.println("going out of bar");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("wait over");
}
}
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final ChangeLockObjectState test = new ChangeLockObjectState();
new Thread(new Runnable() {
#Override
public void run() {
test.bar();
}
}).start();
Thread.sleep(6000);
new Thread(new Runnable() {
#Override
public void run() {
test.foo();
}
}).start();
}
}
The new value is shown. And it works even without the making obj volatile. That's because the sychronization is still hold on the old object and provides visibility to the new value once the waiting thread (t_foo) gets inside. Here is the test:
public class Main3 {
private MyObject obj = new MyObject(1);
void foo()
{
synchronized(obj)
{
System.out.println(obj.number);
obj.doWork();
}
}
void bar()
{
synchronized(obj)
{
System.out.println(obj.number);
obj.doWork();
//force the foo thread to wait at the synchronization point
for(int i = 0; i < 1000000000l; i++);
obj = new MyObject(2); // <<<< notice this line (call it line-x)
}
}
public static void main(String[] args) throws InterruptedException {
final Main3 m3 = new Main3();
Thread t1 = new Thread( new Runnable() {
#Override
public void run() {
m3.bar();
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
m3.foo();
}
});
t1.start();
t2.start();
}
}
class MyObject {
int number;
public MyObject(int number) {
this.number = number;
}
public void doWork() {
}
}
This is unsafe and broken. Changing the object you lock on doesn't work.
When a thread tries to enter a synchronized block it first has to evaluate the expression in parens in order to figure out what lock it needs. If the lock changes after that, the thread doesn't have any way of knowing that, it eventually acquires the old lock and enters the synchronized block. At that point it sees the object and evaluates that, getting the new reference, and calls the method on it with the old (now irrelevant) lock, and without holding the new lock, even though some other thread might have the new lock held and could be executing the method on the same object concurrently.
The new value of obj will be read.
From the standard's section on Happens before:
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
From definition of shared variable:
All instance fields, static fields, and array elements are stored in heap memory. In this chapter, we use the term variable to refer to both fields and array elements.
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
The read of obj inside of the synchronized block is separate from the initial evaluation of the expression obj to determine the which object's build-in monitor to lock. The reassignment of obj will happen before the first read, but not the second. Since obj is a volatile field, that second read must see the updated value of obj.
Can someone explain to me how Reentrant lock and deadlock relate to each other with Java code (pseudo) example?
A reentrant locking mechanism allows the thread holding the lock to re-enter a critical section. This means that you can do something like this:
public synchronized void functionOne() {
// do something
functionTwo();
// do something else
// redundant, but permitted...
synchronized(this) {
// do more stuff
}
}
public synchronized void functionTwo() {
// do even more stuff!
}
In a non-reentrant lock, you would have a deadlock situation when you try to call functionTwo() from functionOne() because the thread would have to wait for the lock...which it holds itself.
Deadlock, of course, is the evil situation in which Thread 1 holds lock A and is waiting for lock B while Thread 2 holds lock B and is waiting for lock A. Thus, neither can continue. This code sample creates a deadlock:
public synchronized void deadlock() throws InterruptedException {
Thread th = new Thread() {
public void run() {
deadlock();
}
}.start();
th.join();
}
The calling thread tries to wait around for the spawned thread, which in turn can't call deadlock() until the caller has exited. Ka-boom!
A deadlock occurs when a thread waits for a condition which will never become true.
The obvious case is when you are trying to lock two locks, locked in a different order by different threads.
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
public void methodA() {
lock1.lock();
lock2.lock();
// do something and unlock both.
}
public void methodB() {
lock2.lock();
lock1.lock();
// do something and unlock both.
}
As you can see it is possible for a thread to call methodA and obtain lock1 waiting for lock2, and another thread to call methodB and obtain lock2 waiting for lock1.
However, it's possible for a thread to deadlock itself. An example is ReentrantReadWriteLock because it doesn't support upgrading a read lock to a write lock.
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
// do we need to update?
rwl.writeLock().lock(); // will wait for the readLock() to be released!
An obscure opportunity to deadlock yourself is when implied locks are used. A static initialiser block is implicitly thread-safe so a lock is used even though static initialiser blocks are not synchronized
class A {
private static int VALUE;
static {
Thread t = new Thread() {
public void run() {
// waits for the A class to load.
VALUE = someLongTask();
}
};
t.start();
// waits for the thread.
t.join();
}
}
Again you have a deadlock!
Here's an example of deadlock with ReentrantLock
class Deadlock {
private static final ReentrantLock l1 = new ReentrantLock();
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("A Trying to lock...");
l1.lock();
System.out.println("A Locked...");
try {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("B Trying to lock...");
l1.lock();
System.out.println("B Must not print");
try {
} finally {
System.out.println("B Trying to unlock...");
l1.unlock();
System.out.println("B Unlocked...");
}
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
System.out.println("A Trying to unlock...");
l1.unlock();
System.out.println("A Unlocked...");
}
}
});
t.start();
}
}
To resolve deadlock, comment out call to t.join, along with enclosing try/catch.
A reentrant lock will allow the lock holder to enter blocks of code even after it has already obtained the lock by entering other blocks of code. A non-reentrant lock would have the lock holder block on itself as it would have to release the lock it obtained from another block of code to reobtain that same lock to enter the nested lock requiring block of code.
As far as deadlock is concerned, if you call a protected block of code from a protected block of code, you'll want a reentrant lock (or you will deadlock while waiting on yourself).