I was reading multi threading in Java from the book Java The Complete Reference by Herbert Schildt. I came across following code [Pg. 252, 7th ed.] that explained the usage of wait() and notify() to suspend and resume threads in modern Java. My question is regarding the significance of the keyword synchronization at two places in following code (in run() method of class NewThread):
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
suspendFlag = false;
t.start();
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized (this) { //First doubt here
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() { //Second doubt here
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
Thread.sleep(1000);
ob1.myresume();
ob2.mysuspend();
Thread.sleep(1000);
ob2.myresume();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
//some code
}
My doubt here: I know about the use of keyword synchronization i.e. allowing only one thread to enter a synchronized method on the same object but here we have two threads running on two different objects. So what is the significance of both synchronization keywords used in above code.
I tried running the above code by removing the synchronized keyword at each place differently and simultaneously. I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner different number of times and at different line numbers depending upon if I remove both or only one (and which one) synchronization keyword. I looked for the above error and found an explanation for it here but still couldn't connect the answer to my doubt.
The problem that synchronized solves is, it allows the two threads to have a consistent view of the shared suspendFlag variable.
In some real program, a thread might set other shared variables before setting susependFlag=false. If synchronized was not used, then the waiting thread could wake up, and see suspendFlag==false, but not see the other variables set. Or worse, it could see some of them set, but not others.
Without synchronization, Java does not guarantee that different threads will see variables updated in the same order.
I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner.
The Java library is trying to help you by forcing you to use synchronized before it will allow you to use wait() and notify(). The rule is simple: You can only call o.wait() or o.notify() or o.notifyAll() from code that is inside a synchronized(o) block. If you break that rule, then the library throws the exception.
When your code calls o.wait() the wait() call temporarily unlocks the monitor lock so that the other thread will be able to synchronize on o and call o.notify(). The o.wait() call is guaranteed to re-lock o before it returns.
Related
I came across the following e example to implement custom suspend and wait from some website.
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
...................
I am more concerned about the ob1.mysuspend() and ob1.myresume() calls. When my suspend is called then ob1 will be placed into the blocking queue associated with the runnable object it is using. When ob1 calls myresume, then how does it work as ob1 is already in waiting queue for the same object, can the waiting object enters another synchronised method and then signals notify to itself?How does this work?What am I missing?
The thread is written so that while an instance of NewThread is running, another thread can call mysuspend to suspend that running thread. Again, a thread other than the suspended thread calls myresume to resume the suspended thread.
There also appears to be a data race because mysuspend writes to suspendFlag without any synchronization. That means, the thread that needs to be suspended may not see that write immediately. mysuspend must be declared synchronized, or suspendFlag must be volatile.
This code is flat out broken.
Straight up broken: JMM violation
The mysuspend method (which should be named mySuspend, by the way) updates a field that is then read from another thread, and isn't synchronized. This is an error - and a really nasty one because you cannot reliably test that it is an error. The Java Memory Model (JMM) states that any write to a field may be observable or not, at the discretion of the JVM implementation, unless a so-called Happens-Before/Happens-After relationship is established (there are many ways to do it; usually you do so via synchronized, volatile, or some other concurrency tool built on these primitives, such as the latches and queues in the java.util.concurrent package).
You do not establish such a relationship here, meaning, that suspendFlag = true results in a schroedingers cat variable: The other thread that reads this field may read true or false, the JVM gets to decide what you see. Hence: A bug, and, untestable. bad. Any field that is read/written to by multiple threads needs to be written extremely carefully.
Mark that method synchronized, that's a good first step.
Wait and Notify
You've got it flipped around: You must in fact hold the synchronized lock on x when you invoke wait on x (here, x is this).
To call x.wait() (you are calling this.wait(), effectively), you must first be in a synchronized(x) block. Once the wait 'goes through', the code releases the lock (other synchronized(x) blocks can run). To invoke x.notify() you must also hold that lock.
wait does not return until the lock is re-established.
In other words:
public void foo() {
wait();
}
will fail at runtime. Try it. Guaranteed exception. In the mean time, this:
public void foo() {
synchronized (this) {
// code before wait
wait();
// code after wait
}
}
is executed as if it is written like this:
public void foo() {
synchronized (this) {
// code before wait
release_lock(this);
this.wait();
acquire_lock(this);
// code after wait
}
}
Where acquire_lock is guaranteed to actually take a while (because by definition whatever invoked notify() to wake you up is currently holding it! So wait is always a two-hit thing: You need to be both notified AND the lock needs to be reacquired before your code will continue). Except, of course, acquire_lock and release_lock don't exist, and unlike this hypothetical code, wait() is more atomic than that.
I am using multi-threading in java for my program.
I have run thread successfully but when I am using Thread.wait(), it is throwing java.lang.IllegalMonitorStateException.
How can I make a thread wait until it will be notified?
You need to be in a synchronized block in order for Object.wait() to work.
Also, I recommend looking at the concurrency packages instead of the old school threading packages. They are safer and way easier to work with.
EDIT
I assumed you meant Object.wait() as your exception is what happens when you try to gain access without holding the objects lock.
wait is defined in Object, and not it Thread. The monitor on Thread is a little unpredictable.
Although all Java objects have monitors, it is generally better to have a dedicated lock:
private final Object lock = new Object();
You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:
private static final class Lock { }
private final Object lock = new Lock();
In order to wait or notify/notifyAll an object, you need to be holding the lock with the synchronized statement. Also, you will need a while loop to check for the wakeup condition (find a good text on threading to explain why).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
It is well worth getting to understand both Java language and java.util.concurrent.locks locks (and java.util.concurrent.atomic) when getting into multithreading. But use java.util.concurrent data structures whenever you can.
I know this thread is almost 2 years old but still need to close this since I also came to this Q/A session with same issue...
Please read this definition of illegalMonitorException again and again...
IllegalMonitorException is thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
This line again and again says, IllegalMonitorException comes when one of the 2 situation occurs....
1> wait on an object's monitor without owning the specified monitor.
2> notify other threads waiting on an object's monitor without owning the specified monitor.
Some might have got their answers... who all doesn't, then please check 2 statements....
synchronized (object)
object.wait()
If both object are same... then no illegalMonitorException can come.
Now again read the IllegalMonitorException definition and you wont forget it again...
Based on your comments it sounds like you are doing something like this:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
There are three problems.
As others have said, obj.wait() can only be called if the current thread holds the primitive lock / mutex for obj. If the current thread does not hold the lock, you get the exception you are seeing.
The thread.wait() call does not do what you seem to be expecting it to do. Specifically, thread.wait() does not cause the nominated thread to wait. Rather it causes the current thread to wait until some other thread calls thread.notify() or thread.notifyAll().
There is actually no safe way to force a Thread instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecated Thread.suspend() method, but that method is inherently unsafe, as is explained in the Javadoc.)
If you want the newly started Thread to pause, the best way to do it is to create a CountdownLatch instance and have the thread call await() on the latch to pause itself. The main thread would then call countDown() on the latch to let the paused thread continue.
Orthogonal to the previous points, using a Thread object as a lock / mutex may cause problems. For example, the javadoc for Thread::join says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?
Are you calling Thread.wait() from within the thread, or outside it?
I ask this because according to the javadoc for IllegalMonitorStateException, it is:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:
private static final class Lock { }
private final Object lock = new Lock();
#Test
public void testRun() {
ThreadWorker worker = new ThreadWorker();
System.out.println ("Starting worker");
worker.start();
System.out.println ("Worker started - telling it to wait");
try {
synchronized (lock) {
worker.wait();
}
} catch (InterruptedException e1) {
String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
System.out.println (msg);
e1.printStackTrace();
System.out.flush();
}
System.out.println ("Worker done waiting, we're now waiting for it by joining");
try {
worker.join();
} catch (InterruptedException ex) { }
}
In order to deal with the IllegalMonitorStateException, you must verify that all invocations of the wait, notify and notifyAll methods are taking place only when the calling thread owns the appropriate monitor. The most simple solution is to enclose these calls inside synchronized blocks. The synchronization object that shall be invoked in the synchronized statement is the one whose monitor must be acquired.
Here is the simple example for to understand the concept of monitor
public class SimpleMonitorState {
public static void main(String args[]) throws InterruptedException {
SimpleMonitorState t = new SimpleMonitorState();
SimpleRunnable m = new SimpleRunnable(t);
Thread t1 = new Thread(m);
t1.start();
t.call();
}
public void call() throws InterruptedException {
synchronized (this) {
wait();
System.out.println("Single by Threads ");
}
}
}
class SimpleRunnable implements Runnable {
SimpleMonitorState t;
SimpleRunnable(SimpleMonitorState t) {
this.t = t;
}
#Override
public void run() {
try {
// Sleep
Thread.sleep(10000);
synchronized (this.t) {
this.t.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
You ask
How can I make a thread wait until it will be notified?
You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
Details for synchronization and waiting are already explained by Tom Hawtin.
java.lang.IllegalMonitorStateException means you are trying to wait on object on which you are not synchronized - it's illegal to do so.
Not sure if this will help somebody else out or not but this was the key part to fix my problem in user "Tom Hawtin - tacklin"'s answer above:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
Just the fact that the "lock" is passed as an argument in synchronized() and it is also used in "lock".notifyAll();
Once I made it in those 2 places I got it working
I received a IllegalMonitorStateException while trying to wake up a thread in / from a different class / thread. In java 8 you can use the lock features of the new Concurrency API instead of synchronized functions.
I was already storing objects for asynchronous websocket transactions in a WeakHashMap. The solution in my case was to also store a lock object in a ConcurrentHashMap for synchronous replies. Note the condition.await (not .wait).
To handle the multi threading I used a Executors.newCachedThreadPool() to create a thread pool.
Those who are using Java 7.0 or below version can refer the code which I used here and it works.
public class WaitTest {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitHere(long waitTime) {
System.out.println("wait started...");
lock.lock();
try {
condition.await(waitTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
System.out.println("wait ends here...");
}
public static void main(String[] args) {
//Your Code
new WaitTest().waitHere(10);
//Your Code
}
}
For calling wait()/notify() on object, it needs to be inside synchronized block. So first you have to take lock on object then would be possible to call these function.
synchronized(obj)
{
obj.wait()
}
For detailed explanation:
https://dzone.com/articles/multithreading-java-and-interviewspart-2
wait(), notify() and notifyAll() methods should only be called in syncronized contexts.
For example, in a syncronized block:
syncronized (obj) {
obj.wait();
}
Or, in a syncronized method:
syncronized static void myMethod() {
wait();
}
It might seem to be a very naive question but I cannot find any concrete answer anywhere. I tried it even practically but since we cannot predict the behaviour of threads resource allocation in Java, it's really difficult to determine.
I just want to know if I can access a synchronized method and and unsynchronized method of a class at the same time from two different threads of same instance of that class ?
Don't see any problems. Try out this:
public class Main {
public static final SyncNotsynced sn = new SyncNotsynced();
public static void main(String[] args){
Thread t1 = new Thread(sn::synced);
Thread t2 = new Thread(sn::notsynced);
t1.start();
t2.start();
}
public static class SyncNotsynced {
public synchronized void synced(){
System.out.println(Thread.currentThread().getName() + " enter synced");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " exit synced");
}
public void notsynced(){
System.out.println(Thread.currentThread().getName() + " enter notsynced");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " exit notsynced");
}
}
}
or take look at the live example :). As you can see enterings of Thread 1 and Thread 2 are both happened before exiting:
Thread-0 enter synced
Thread-1 enter notsynced
Thread-0 exit synced
Thread-1 exit notsynced
For a formal explanation you can read JLS 17, but in short only one thread can enter a synchronized block on the same object monitor.
Btw, I used Thread.sleep because (emphasize mine):
Thread.sleep causes the currently executing thread to sleep
(temporarily cease execution) for the specified duration, subject to
the precision and accuracy of system timers and schedulers. The thread
does not lose ownership of any monitors, and resumption of execution
will depend on scheduling and the availability of processors on which
to execute the thread.
Why usually threading samples put so many code in synchronized block. According to my understanding in following case synchronized is used just for locking b for wait and notify:
Main class ThreadA :
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
System.out.println(Thread.currentThread().getName());
}
}
}
and class ThreadB:
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this)
{
System.out.println();
for(int i=0;i<100;i++)
{
System.out.println(Thread.currentThread().getName());
total += i;
}
notify();
}
}
}
What will change if I put just wait and notify in synchronized block:
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
try {
System.out.println("Waiting for b to complete...");
synchronized(b) { b.wait();}
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
System.out.println(Thread.currentThread().getName());
}
}
According to my understanding in following case synchronized is used just for locking b for wait and notify
Your understanding is wrong.
synchronized is also used for:
Mutual exclusion, to ensure that only one thread executes code "guarded" by a particular monitor at a time
Ensuring memory access across threads is correct (that one thread sees changes made by another thread)
What will change if I put just wait and notify in synchronized block:
In this particular case, it will make a difference based on a race condition - in the original code, if the new thread starts executing before the synchronized block is reached in the original thread, it won't get as far as "Waiting for b to complete" until the second thread has finished... at which point it will block forever in wait.
Note that it's a really bad idea to wait on Thread monitors, as wait/notify is used internally by Thread.
In short, the example you've used is a bad one to start with in various ways - but synchronization is used for more than just wait/notify.
Please note that total += i is not an atomic operation in Java. So you have to sync also this construct.
You also have not to sync notify() and wait() because their locks are handled internally.
Expanding on the answer by #sk2212, the increment operation is not atomic, but there is an equivalent atomic operation provided in high-level concurrency primitives.
I am studying K&B threads chapter. I was reading about synchronization. Here is an example from
K&B.
public class AccountDanger implements Runnable {
private Account account = new Account();
public void run() {
for(int x =0 ; x < 5 ; x++){
makeWithdrawl(10);
if(account.getBalance() < 0 ){
System.out.println("account is overdrawn");
}
}
}
public static void main(String[] args){
AccountDanger accountDanger = new AccountDanger();
Thread one = new Thread(accountDanger);
Thread two = new Thread(accountDanger);
one.setName("Fred");
two.setName("Lucy");
one.start();
two.start();
}
private synchronized void makeWithdrawl(int amt){
if(account.getBalance() >= amt){
System.out.println(Thread.currentThread().getName() + " is going to withdraw");
try{
Thread.sleep(500);
}
catch(InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName() + " completes the withdrawl");
}
else{
System.out.println("Not enough in account for " + Thread.currentThread().getName() + " to withdraw " +
account.getBalance());
}
}
}
K&B talks about synchronized methods and synchronized blocks. Here is referring paragraph from K&B.
When a method is executing code from within synchronized block, code
is said to be executing in a synchronized context. When you
synchronize a method, the object used to invoke the method is the
object whose lock must be acquired. But when we synchronize block of
code, you must specify which object's lock you want to use as a lock.
So in this example, will the lock be acquired on AccountDanger instance or Account object?
I think so it should be AccountDanger. Am i perceiving correct? If it is AccountDanger object,
and one thread has got the lock of AccountDanger, will any other thread be able to call non-synchronized methods?
So in this example, will the lock be acquired on AccountDanger
instance or Account object?
Yes. One trick I've seen used a lot is to synchronize on this when you have only a small block of code that actually needs to be synchronized. For example:
int balance = -1;
synchronized(this) {
balance = account.getBalance();
account.withdraw(amt);
}
//IO, etc. after that.
In general this speeds things up.
private synchronized void makeWithdrawl(int amt){
//is implicitly acquiring lock on this object (AccountDanger object)
}
So in the example the first thread to call this method will enter the synchronized block acquiring this object monitor and holds it and no other thread except the first thread itself can acquire the monitor lock again on this. All the other threads that call this method will block until the first thread releases the lock and frees the monitor.
Note: Locks used for synchronized blocks are Re-entrant in nature.