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.
Related
I'm new to Java multi threading and little confused with how Java join and wait works.
I have the following example
public class Main {
private static int counter;
static class RunnableThread implements Runnable {
private static final String PREFIX = "RT-";
public RunnableThread() {
}
#Override
public void run() {
counter++;
System.out.println(PREFIX+counter);
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread rt = new Thread(new RunnableThread());
//Thread tt = new TradThread();
rt.start();
//tt.start();
try {
rt.wait();
} catch (InterruptedException e1) {
System.out.println("Main thread wait is interrupted");
e1.printStackTrace();
}
System.out.println("MT-"+counter);
}
}
It throws IllegalMonitorStateException as the main thread doesn't hold any monitor. Now in the same code if I change rt.wait() to rt.join() it works.
When I see how join is implemented it looks like it calls the wait() method. Now how is the call to wait from inside the join valid?
I would assume The Main thread when it calls rt.join() the code in the join method is being executed by the Main thread itself.
Please help me to understand this.
Thanks
Thread.join() and Object.wait() are very different.
t.join()
Join current thread where you are behind thread t. So, current thread will not run until thread t finishes its work.
o.wait()
Release the lock of object o and pause current thread. So, current thread will not run until it obtains the lock of object o again by o.notify() or o.notifyAll() from other thread.
Note: you must have obtained the lock of object o before invoking this method.
Technically, in the join code, we have:
wait(0);
...
wait(delay);
in this case, this is the same as calling this.wait(). So to answer the question, the wait function being called is the object referenced by rt wait method.
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.
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();
}
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();
}
}
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).