I am getting into Java multithreading. I am very familiar with C/C++ pthreads, but am having issues with the Java notify() and wait() functions.
I understand that an IllegalMoinitorStateException is only thrown when a thread that doesnt "own" (aka hasnt synchronized) calls notify/wait.
When writing my application, I ran into this issue. I isolated the problem with the following test code:
public class HelloWorld
{
public static Integer notifier = 0;
public static void main(String[] args){
notifier = 100;
Thread thread = new Thread(new Runnable(){
public void run(){
synchronized (notifier){
System.out.println("Notifier is: " + notifier + " waiting");
try{
notifier.wait();
System.out.println("Awake, notifier is " + notifier);
}
catch (InterruptedException e){e.printStackTrace();}
}
}});
thread.start();
try{
Thread.sleep(1000);
}
catch (InterruptedException e){
e.printStackTrace();
}
synchronized (notifier){
notifier = 50;
System.out.println("Notifier is: " + notifier + " notifying");
notifier.notify();
}
}
}
This outputs:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at HelloWorld.main(HelloWorld.java:27)
I believe I have already acquired the lock on the notifier object. What am I doing wrong?
Thanks!
EDIT:
From this possible duplicate(Synchronizing on an Integer value), it seems that it is not a good idea to synchronize on an Integer because it is hard to make sure you are synchronizing on the same instance. Since my integer I am synchronizing on is a global visibile static integer, why am I getting different instances?
Because of notifier = 50; you are calling notifier.notify(); on a different object.
Initially when you calling synchronized on notifier in non-main Thread it was referencing to the object on heap whose content was 0 hence the thread owns that object . Now after non-main thread is put on wait using notifier.wait the control is given to the main thread . There after acquiring lock on object of Integer containing value 0 you made the notifier to refer the other object on heap memory containing value 50 because notifier = 50; is actually equivalent to notifier = new Integer(50) which means a new object of Integer is created and its reference is passed to notifier. Now , when the thread sees notifier.notify it looks that the Main thread now no longer owns the original object that it had acquired before. So IllegalMonitorStateException is throwing.
Just to add more information, you should never synchronize on a non-final object.
You need to synchronize on a constant object. If you synchronized on any object that you are assigning (i.e. changing the object) then the object is not constant and once it assigns the object and tries to notify on it, you will get the IllegalMonitorStateException. It also means that because they are synchronizing on different objects, multiple threads will be entering the protected block at the same time and race conditions will happen.
Since my integer I am synchronizing on is a global visibile static integer, why am I getting different instances?
When you assign a value to an Integer it changes it to a different object reference -- even if it is static. You are not changing the same object because Integer can't be mutated. So notifier = 50; assigns it to a different object than notifier = 0;.
If you want to use, for example, a constant object you can use an AtomicBoolean:
public static final AtomicInteger notifier = new AtomicInteger(0);
...
synchronize (notifier) {
notifier.set(50);
...
}
Here, AtomicInteger can be marked final because it's the same object all of the time.
For more information, see: Why is it not a good practice to synchronize on Boolean?
Related
I have the following piece of code. It has two objects, namely MultiThreadingTest, and the ThreadB object. When we say synchronized(b), what does it mean exactly? Can the 'main' thread get a lock on b before ThreadB finishes it's execution? I can't understand the significance of monitor object in the synchronized block.
package threads;
class MultiThreadingTest
{
public static void main(String[] args)
{
ThreadB b = new ThreadB();
b.setName("Thread B");
b.start();
synchronized(b)
{
System.out.println("Current thread : "+ Thread.currentThread().getName());
try
{
System.out.println("Waiting for b to complete...");
b.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Total = "+b.total );
}
}
}
class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("Current thread : "+Thread.currentThread().getName());
for(int i=0;i<100;i++)
{
total = total + i;
}
notify();
}
}
}
Think of it like the child's game, whoever holds the [whatever object] gets to speak. Whoever holds the monitor object gets to execute in computing terms.
The monitor is the object you are locking upon, at any given time, only one thread accesses code protected by a synchronization block per monitor object. The object itself is arbitrary and doesn't hold much weight onto synchronization (though you have to watch out for reassigning variables as well as null references). Also, JB Nizet raises a good point here on synchronizing on a Thread object since many internal VM methods do that, you can cause bazaar, hard to detect bugs and deadlocks.
Two threads entering different synchronization blocks locking on different monitors will execute concurrently, analogous to two separate groups of people playing/enacting the "who ever holds to xxx gets to speak" game. Locking on this is just a convenient way to manifest a single lock synchronization without creating additional lock objects.
In your case, ThreadB b is the same object pointed to as this from within the ThreadB class meaning that only one thread can enter any of your defined synchronization blocks at once. The order is highly dependent on which thread ran first, the thread scheduler and even the underlying system.
The main reason for monitor objects is so that complex thread-safety mechanisms can be realized. Imagine a system where every synchronization block is single thread access (i.e. at any time, any thread enters a synchronization block will hold every other thread in the whole VM trying to enter a sync block) not only will this cause a massive performance slowdown, it just doesn't make sense. Why should two unrelated application modules lock on each other if they share no data and never interact?
The solution of course is to have one module use one (or several) monitor objects that are unrelated/unassociated with the other module, so both can execute concurrently independent of each other (assuming this is the desired behavior).
To further clarify, you could write:
class MultiThreadingTest{
public static void main(String[] args){
ThreadB b = new ThreadB();
b.setName("Thread B");
b.start();
synchronized(b.lock){
System.out.println("Current thread : "+ Thread.currentThread().getName());
try{
System.out.println("Waiting for b to complete...");
b.lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total = " + b.total );
}
}
}
class ThreadB extends Thread{
public final Object lock = new Object();
int total;
public void run(){
synchronized(lock){
System.out.println("Current thread : "+Thread.currentThread().getName());
for(int i = 0; i < 100; i++){
total = total + i;
}
lock.notify();
}
}
}
to exactly the same effect as the code you've used (even better, since it resolves the conflict with Thread.join() and other methods).
synchronized(this) means that you won't be able to enter this block of code if another thread is inside a block of code that is also synchronized on the object referenced by this.
synchronized(b) means that you won't be able to enter this block of code if another thread is inside a block of code that is also synchronized on the object referenced by b.
They thus do the exact same thing. The only difference is the object that is used to lock.
Note that waiting, synchronizing and notifying on an object of type Thread is a really really bad idea. It confuses things, and will lead to unwanted behavior because other methods (join() for example) also use the Thread as a monitor.
As per my understanding, no. The 'this' object within the run() method and the 'b' object in the main() method are the same.
Hence it would not be possible for the 'main' thread to acquire the lock until the thread completes execution.
Also the notify() within the run() method seems to be redundant in this case since its at the end of the method and the lock on the monitor would be relinquished any how.
PS: Do look around for similar questions that may already have been asked in the forum. They may help in providing additional understanding.
I am trying to get familiar with wait() and notify() methods and I have written a simple class acting like a monitor for a simple producer-consumer excercise where there are N producers and N consumers. Anyway the monitor, as requested in the excercise, can store only 3 items. So the producers must wait; on the contrary if there are 0 items in the monitor the consumers must wait.
public class Monitor {
private List<Integer> items;
private int capacity;
private Object waitProducer;
private Object waitConsumer;
private int counter;
public Monitor() {
this.items = new ArrayList<Integer>();
this.capacity = 3;
this.waitProducer = new Object();
this.waitConsumer = new Object();
this.counter = 0;
}
public void produce() throws InterruptedException {
synchronized (this) {
if (this.items.size() == this.capacity) {
synchronized (this.waitProducer) {
System.out.println("Producer " + Thread.currentThread().getId() + " aspetta");
this.waitProducer.wait(); /***/
}
}
counter++;
System.out.println("Thread " + Thread.currentThread().getId()
+ " produces object " + counter);
this.items.add(counter);
synchronized (this.waitConsumer) {
this.waitConsumer.notify();
}
}
}
public void consume() throws InterruptedException {
synchronized (this) {
if (this.items.size() == 0) {
synchronized (this.waitConsumer) {
this.waitConsumer.wait(); /***/
}
}
System.out.println("Thread " + Thread.currentThread().getId()
+ " consume object " + this.items.get(0));
this.items.remove(0);
synchronized (this.waitProducer) {
this.waitProducer.notify();
}
}
}
}
I think that there is a problem in lines with /***/: infact when the wait() method is invoked then the thread releases the lock on waitProducer (or waitConsumer) but it does not on the Monitor object. That's why when the first produces (of the first consumer) calls wait() then the Monitor object is no more obtainable. Obvioudly the access to the Monitor object must be in mutual exclusion so that to update correctly the list and the counter. So, what is the correct way? Thanks
Only one thread can execute the code inside synchronized blocks at a time.
Also, one must gain an exclusive lock on an object (via synchronized(object)) when calling wait() on that object.
This means, the unlocking/unblocking/notify code must be accessible to other threads outside of original block which called wait(). Otherwise, execution will wait forever.
In your code no other thread can reach this.waitConsumer.notify(); while one thread waits on this.waitProducer.wait();. Because all of it is also enclosed in a synchronized(this) block, other threads will keep contesting for locking on this.
#james large What do you mean that two threads can be synchronized in the same block if they are synchronized on different objects?
Suppose you have a synchronized block that looks like this:
synchronized(obj) {
...body of synchronized block...
}
...whatever happens next...
When Java thread T executes that statement, it starts by evaluating the expression, obj. That expression must either return null, or it must return a reference to an object. If it's null, then a NullPointerException will be thrown. Otherwise, thread T will attempt to lock the object.
No two threads can ever lock the same object at the same time. If the object already was locked by some other thread, then thread T will be unable to proceed until the object is unlocked.
When thread T finally is able to lock the object, it will execute the body of the synchronized block, and then it will unlock the object and move on to whatever happens next.
The important concept here is the expression, obj. Suppose that thread T evaluates obj, gets a reference to object O, locks it, and enters the synchronized block. Then thread U comes along, evaluates obj, gets a different object, P. Thread U will lock object P, and will be able to enter the synchronized block while thread T still is in there at the same time.
So how can that happen?
When it's intended, it might look like this:
class MyClass {
private final Object lock = new Object();
void foobar() {
synchronized(lock) { ... }
}
}
If thread T and thread U are operating on different instances of MyClass, then each instance will have its own lock object. Usually, in this case, the body of the synchronized block will only operate on other instance variables of MyClass. Since the two threads are operating on different data, there is no harm in them both being in the same synchronized block at the same time.
The purpose of synchronization is not to keep two threads out of the same method at the same time: The purpose is to keep two threads from operating on the same data at the same time.
Sometimes a newbie programmer writes this:
static Integer count = new Integer(0);
...
synchronized(count) {
count += 1;
...operate on static data...
}
This is almost always a mistake. When thread T enters the block, it will synchronize on the Integer object that is referenced by the static variable count. But then the next thing it does is update count to refer to a different Integer object. Then along comes thread U. U synchronizes on the new count, and both threads are in the same block, operating on the same static data when they should not.
public class Computation extends Thread {
private int num;
private boolean isComplete;
public Computation(int nu) {
num = nu;
}
public void run() {
System.out.println("Thread Called is: " + Thread.currentThread().getName());
}
public static void main(String... args) {
Computation [] c = new Computation[4];
for (int i = 0; i < 3; i++) {
c[i] = new Computation(i);
c[i].start();
}
}
}
My Question is in main function we are creating every time a new Computation object on which the thread is being started then why we need to snchrnoized the run method? As we know for every different class object 'this' reference is different so we don't need to synchronize.
Also in another Example:
public class DiffObjSynchronized implements Runnable {
#Override
public void run() {
move(Thread.currentThread().getId());
}
public synchronized void move(long id) {
System.out.print(id + " ");
System.out.print(id + " ");
}
public static void main(String []args) {
DiffObjSynchronized a = new DiffObjSynchronized();
/**** output ****/
// 8 9 8 9
new Thread(a).start();
new Thread(new DiffObjSynchronized()).start();
}
}
Here is second example just like first we create a Thread on 2 different instances of class. Here we synchronize the move() method but by definition:
"two different objects can enter the synchronized method at the same time"
Please share your feedback?
If I understand you correctly, your question is: "Why is the move method synchronized?"
The answer is: it shouldn't be, for two reasons:
It doesn't access any fields, so there is nothing that could be corrupted by having many threads inside that method at once.
Each thread gets a different instance of the object, and thus a different lock. So the synchronized modifier makes no difference. Each thread can still enter its own instance's move method because they have separate locks.
You only need to synchronize when you have some data which is being shared between threads, and at least one thread is modifying that data.
Your threads are operating on different objects since you create a new instance for each thread. The intrinsic lock used by synchronized belongs to the instance. So the synchronized methods entered by your threads are guarded by different locks.
You need to understand how synchronization works.
Threads take a 'lock' on the object on which you are synchronizing when they enter the synchronized block. If you have a synchronized method then in that case the object becomes the 'this' instance. Now, no 2 threads can take a lock on the same object at the same time. object locks are mutex based in philosophy so only once thread can hold the mutex at a time. When the thread holding the lock exits the synchronized method or the block, it releases the mutex and thus the object lock becomes available to other threads to request lock on.
This link explains the concepts excellently. It has pictures about disassembled byte code which shows how threads take and leave locks and why 2 threads on 2 different object dont block each other.
If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
public static void main(String[] args) {
A a = new A();
new Thread(new MyRunnable(a), "T1").start();
new Thread(new MyRunnable(a), "T2").start();
}
static class MyRunnable implements Runnable {
A a;
public MyRunnable(A a) {
super();
this.a = a;
}
#Override
public void run() {
while (true) {
if ("T1".equals(Thread.currentThread().getName())) {
a.m1();
} else {
a.m2();
}
}
}
}
static class A {
StringBuilder abc = new StringBuilder("fdfd");
public void m1() {
synchronized (abc)
{
System.out.println("abc locked : " + abc);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();}
System.out.println("abc released: " + abc);
}
}
public void m2() {
System.out
.println(Thread.currentThread().getName() + " running");
System.out.println("trying to access abc");
abc.append("A");
System.out.println("abc accessed");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
}
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
OUTPUT:
abc locked : fdfd
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc released: fdfdAA
abc accessed
abc locked : fdfdAAA
T2 running
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
Uh yes. I think you need to do some reading about what synchronized does. See the Java tutorial. It does not "lock" an object as in restrict other threads from operating on it. What it does is provide mutex for the surrounded block of code for threads that lock on the same object instance. The fields in an object are perfectly able to be mutated both inside or outside the synchronized block.
It is always a good idea to synchronize on a constant object so I tend to do something like:
private final Object lock = new Object();
...
synchronized (lock) {
// only one thread allowed inside this block at a time
}
If multiple threads are accessing some sort of thread-unsafe object, I will synchronize on that object and do the operations on the object inside the synchronized block:
private final SomeUnsafeObject someObject = ...;
...
synchronized (someObject) {
// only one thread allowed inside this block at a time
someObject.someUnsafeMethodCall(...);
}
// no accesses (read or write) outside of the synchronized block
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
No, there is no implicit blocking of the object being changed. If you only access the object's fields inside of the synchronized block then you would have accomplished what you want.
public void m2() {
...
abc.append("A");
Right, since you are not inside of a synchronized (abc) block here, there is nothing that stops the thread from calling abc.append(...).
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
Synchronization allows you to control access to a block of code to one thread at a time based on the lock object (or the monitor on that object to be precise). It also allows you to do lock.wait(...) and lock.notify(...) to control the threads operation and block/release them as well.
Synchronization also puts up memory barriers so that a thread will see changes stored to central memory when it enters a synchronized block and will see it's changes written to central memory when it leaves. Without these memory barriers, if other threads access the StringBuilder without synchronization then they may seem some partially updated portion of that class which can cause NPEs or other failures.
A thread will only have to wait to access a locked code region, if that lock is held by another thread. However, it doesn't have to wait if it doesn't need a lock, i.e., your StringBuilder instance is only safe if every access is surrounded by a synchronized block locking on the same lock.
In your case, since access to abc in method m2() is not in synchronized block, a thread doesn't need a lock, and hence can access it.
When you are synchronizing on a Lock object the lock object has to be accessible by all threads, so either use a static object or a field belonging to the calling code.
Then you code will work to have only only one thread at a time accessing a certain block(s) of code. It will not prevent you acting in that code in anyway that you wish, but only one Thread can do it at one time.
public class Fern extends Thread
{
private String x = "varun";
public void run()
{
synchronized(Fern.class){
System.out.println(x);
try {
sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x = "Anku";
}
}
public static void main(String args[]) throws Exception
{
Fern f = new Fern();
Thread t1 = new Thread(new Fern());
Thread t2 = new Thread(new Fern());
t1.start();
t2.start();
}
}
Output is:
varun
varun
Since the block has been synchronized on Fern.class, only one thread should be allowed to enter the block at a time irrespective of which instance it belongs to since there is only one lock for the class for all instances. If I replace new Fern() in the Thread constructor with a single Fern object, the output is:
varun
Anku.
The behaviour is what would have been had I synchronized on(this).
I dont understand why this is happening since I synchronized
x is not a static variable. Change it to static.
static String x = "varun";
EDIT:
or pass the same object as parameter to t1 and t2.
Fern f = new Fern();
Thread t1 = new Thread(f); // pass the same object
Thread t2 = new Thread(f);
x is an instance variable - in other words, even though only one thread can enter that block at a time, they're looking at different variables. Changing the value of x in the first thread doesn't affect the x that the second thread is looking at.
In other words, the synchronization is "correct" (if you don't want more than one thread to enter that block regardless of instance) but your data access isn't doing what you think it should.
As a side note, I personally prefer locking on references which only my class can see.
As another side note, it would be better if Fern implemented Runnable rather than extending Thread - you're currently passing one thread to another one's constructor, which doesn't make much sense...
The x in each instance of the thread is a different one. Try private static String x to use a shared x in both cases.
This has nothing to do with synchronization. x is an instance variable, so each Fern instance has its own copy, initialized to "varun", then printed, then set to "Anku".
Because you have two different Fern instances, the fact that one of them changes the value of its x field is not seen by the other. (I am guessing, since you don't give the declaration of x. To get better answers, post only complete code.)