Reputation: 2561
I am reading and trying to understand the wait and notify mechanism in the thread. For that i need to clear my concepts, hence to just make sure about my concept i am asking question on the examples tried, as follows
Please follow the code snippet,
class CodeOne implements Runnable{
@Override
public void run(){
try{
synchronized(this){
for(int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+" : "+i);
Thread.sleep(500);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class ThreadPractiseOne{
public static void testOne() throws Exception{
CodeOne code = new CodeOne();
Thread t1 = new Thread(code,"THREAD-ONE");
Thread t2 = new Thread(code,"THREAD-TWO");
t1.start();
t2.start();
}
public static void main(String[] args){
try{
testOne();
}catch(Exception e){
}
}
}
From the above code we can see the sunchronized block uses 'this' as argument. the purpose of it is that, the threads created in the main method acquire lock on the object CodeOne and hence only one thread is able to access it.
Is my above understanding correct ?
if yes,
than i want to ask one more question on the basis of the code written as follows,
public class MyThread extends Thread{
public MyThread(String name){
this.setName(name);
}
public int total;
@Override
public void run(){
try{
synchronized(this){
System.out.print(" ");
for(int num=1; num <= 3; num++){
total += num;
System.out.print("..");
Thread.sleep(1000);
}
System.out.println("\n");
notify();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class MainThread {
public static void main(String [] args){
MyThread t1 = new MyThread("ONE");
try{
t1.start();
synchronized(t1){
System.out.println(" Waiting for Thread ONE to complete ");
t1.wait();
}
System.out.println(" TOTAL is "+t1.total);
}catch(Exception e){
e.printStackTrace();
}
}
}
From the above code we can see here in the main method of class MainThread
, i have used synchronized block but the argument passed i t1 i.e the thread instance.
is this mean that the main thread acquires a lock on 't1' ?
if yes why ?
and if i do
synchronized(new MainThread())
in the MainThread
class, i get an exception
java.lang.IllegalMonitorStateException
why ?
by the way the output of the 2nd program is
Waiting for Thread ONE to complete
......
TOTAL is 6
Upvotes: 0
Views: 100
Reputation: 116938
the threads created in the main method acquire lock on the object CodeOne and hence only one thread is able to access it.
Yes this is correct. It is very important to realize that they are locking on the same instance of CodeOne
. Locks only work if multiple threads are synchronized
on the same object instance.
is this mean that the main thread acquires a lock on 't1' ?
Yes. Both the main thread and the forked thread both are locking on the same Thread
instance. As an aside it is considered a better pattern to define your class to implements Runnable
instead of extending Thread
. For example, other parts of the Thread
code lock on the Thread
instance. Since you are locking on it is as well this may cause some unintended consequences.
It is also important to realize that just calling notify();
is a bad pattern. You should explicitly say this.notify();
. They do the same thing but it should have parity between synchronized (this) { ... this.notify(); }
.
is this mean that the main thread acquires a lock on 't1' ?
Yes. The main thread is locking on t1
and inside of the thread it is locking on this
. So they are locking on the same object instance. I'm not sure how to answer the "why" question.
java.lang.IllegalMonitorStateException
This happens when you are trying to do a wait()
or notify()
without being inside of a synchronized
block. In your case if you say:
synchronized(new MainThread()) {
...
notify();
}
Then you are synchronizing on one object and trying to notify on a different object that you don't have locked. The lock object is typically supposed to be a private final
object instance shared by multiple threads. Doing something like synchronized (new ...)
is really never a good pattern.
Upvotes: 1
Reputation: 280172
From the above code we can see the synchronized block uses 'this' as argument. the purpose of it is that, the threads created in the main method acquire lock on the object CodeOne and hence only one thread is able to access it.
Only one thread at a time is able to access code inside a synchronized
block that is synchronized on that object.
is this mean that the main thread acquires a lock on 't1' ?
In this example, this
and t1
happen to refer to the same MyThread
object.
in the MainThread class, i get an exception
You will have to show us the code that actually causes this, but you can't call notify
or wait
on objects which you haven't synchronized
on.
by the way the output of the 2nd program is
This depends on a race condition. It depends on which Thread
acquires the lock on the MyThread
object first. If it's the main thread, then that's the output you will get. If it's the other thread, those lines will be reversed.
I don't see a question on wait()
and notify()
so I'll just refer to Gray's answer, who has given a general explanation.
Finally, don't ever synchronized
on Thread
objects. They have different behavior than normal objects when the actual thread they are referring to comes to an end.
Upvotes: 1