Behind Synchronized Block - java

Synchronized blocks in Java is a great feature when working in multiple threads, which is pretty often. I know most of how they work, but would like to be more sure of how they work when combined with wait and notify(All).
Normally when one thread enters an synchronized block, no other thread can enter this block until the first thread has left. This however is not the case when calling wait on the synchronized object. If it did, another thread would not be able to call notify(All), which requires synchronization with the object before it is called.
So does the call to wait take the call out of the synchronization? Or does java just make an exception if it finds notify(All) within a different block? Also when calling wait from one synchronized block and then notify(All) from another, does one thread wait for the other to finish before continuing, if so, which one?
Now I could setup a quick test to answer most of this, that I am aware of. But it is not going to answer the more technical stuff, which I am sure that someone here can. I am not just interested in the what and when, but also the why. Tried searching for some documented info, but could not find anything useful about wait/notify(All).
EDIT:
If others should be interested, this is the test result. If we have Thread1, Thread2 and Thread3 where the first two waits to be release and the third is the one to release them, the order will go like this.
Thread1 enters and calls wait()
Thread2 enters and calls wait()
Thread3 enters and calls notifyAll()
Thread3 finishes, always
The waiting threads however has no specific order. Which one is executed first, is completly random and has nothing to do with the order in which they called wait(). The thread calling notify(All) however will always finish before any waiting threads continues.

Yes, it is somehow special. wait releases the lock acquired in the synchronized block and and suspends it's thread (the thread that acquired the lock) which means other threads will be allowed to acquire the lock and modify the state.
Now notify or notifyAll will wake up the thread/s that were asleep and they reacquire the lock

Related

where are the threads waken up from Object.notifyAll and failing to get the lock?

Below is how monitor works:
monitor
Threads in wait set are waken up when Object.notifyAll() is called.
Only one of them get the lock, while the others are blocked again.
So where do the blocked threads go?Will they go back to wait set or go to entry set?Or this is managed by the os, because monitor depends on the os MutexLock?
The monitor is a fundamental conception that you should understand. It is better to read about it somewhere.
In short, I could say that there are some major principles:
If a thread go into the synchronized block - the monitor of synchronized object is blocked and all other threads couldn't
execute the synchronized block (they are in the Entry Set).
If you call wait() method on synchronized object, then the thread go to Wait Set
If you call notify()/notifyAll() method on synchronized object, it means that one/all thread(s) go to Entry Set from Wait Set.
The answer to your question is - when you call notifyAll() method, all threads from Wait Set go to Entry Set.

How can we use notifyAll to ensure that only one thread continues after wakeup?

From Programming Language Pragmatics, by Scott
To resume a thread that is suspended on a given object, some other
thread must execute the predefined method notify from within a
synchronized statement or method that refers to the same object. Like
wait, notify has no arguments. In response to a notify call, the
language run-time system picks an arbitrary thread suspended on the
object and makes it runnable. If there are no such threads, then the
notify is a no-op. As in Mesa, it may sometimes be appropriate to
awaken all threads waiting in a given object; Java provides a built-in
notifyAll method for this purpose.
If threads are waiting for more than one condition (i.e., if their waits are embedded in dissimilar loops), there is no guarantee that
the “right” thread will awaken. To ensure that an appropriate thread
does wake up, the programmer may choose to use notifyAll instead of
notify. To ensure that only one thread continues after wakeup, the
first thread to discover that its condition has been satisfied must
modify the state of the object in such a way that other awakened
threads, when they get to run, will simply go back to sleep.
Unfortunately, since all waiting threads will end up reevaluating
their conditions every time one of them can run, this “solution” to
the multiple-condition problem can be quite expensive.
When using notifyAll, all the awaken threads will contend to reacquire the lock, but only one can reacquire the lock, then return from wait() and then reevaluate the condition. So why does it say that "all waiting threads will end up reevaluating their conditions every time one of them can run"?
How does the thread, which reacquires the lock and rechecks that the condition become true, "modify the state of the object in such a way that other awakened threads, when they get to run, will simply go back to sleep"?
Thanks.
So why does it say that "all waiting threads will end up reevaluating their conditions every time one of them can run"?
After it will reacquire and release the lock a different thread will aquire it and run. This will continue until they all do that.
How does the thread, which reacquires the lock and rechecks that the condition become true, "modify the state of the object in such a way that other awakened threads, when they get to run, will simply go back to sleep"?
All the threads will have something like:
while (condition) {
wait();
}
The notifyAll() caller will set condition to false before calling it and then the awakened thread will exit the while loop and before it returns and releases it will do:
condition = true;
All the other threads will awaken, check the condition, stay in the while loop and call wait() (go back to sleep).
Additionally, you should use explicit locking mechanism because it allows you to have multiple conditions and condition queues for a single lock, which will enable you to use signal() instead of signalAll(). And that has better performance and less contention.
Condition API

In Java, how can other thread get chance to run after current thread is called on sleep() but still holds the lock?

In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run. This is done by calling sleep().
However, different from calling wait(), the thread, after calling sleep(), will NOT release the lock it's been holding. Since this thread is still holding the lock, how can other thread get chance to run while not being able to get the unreleased lock?
They can't; other threads that need to acquire a lock held by a sleeping thread will block until they can get it. There's no way to back off like tryacquire on explicit Locks, so the threads are stuck.
Threads shouldn't sleep while holding a lock. If a thread isn't doing something useful it doesn't need to be holding a lock.
To go dormant and release a lock use the wait method. Sleep doesn't have any means to cut its sleep time short other than interruption (which should be used for cancellation), wait lets the thread be notified.
If you call Thread.sleep() while holding a lock or from inside a synchronized block/method, any other threads that reach that lock will wait until the first thread resumes and releases the lock.
However locks/synchronization are not global, any threads that don't reach the locks held by the sleeping thread can run without issue.
If other thread can't get the lock to run while this thread is going to sleep, then what's the purpose for this thread to go sleep at first place?
The only person who can answer that question is the person who wrote the code that runs in the thread.
Was that you?
As Nathan Hughes said, it practically never is a good idea for a thread to sleep() while holding a mutex lock. To take that idea a little further: It almost never is a good idea for a thread to do anything that takes more than a microsecond or so while holding a mutex lock. If you find yourself writing code that waits for something while keeping a lock locked, then that's a sign that you might need to re-think the architecture.
Also, there are not many good reasons for calling sleep() at all.
In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run.
That's not really what sleep() is for. In most cases, when a thread doesn't need the CPU, it will block in a wait() call or in some xyz.await() call (where xyz is a queue or a semaphore or a latch or some other higher-level synchronization object).
The sleep() function is a low-level, primitive that your program can call in order to meet real-time requirements. But most programs with real-time requirements can make use of higher-level facilities such as java.util.concurrent.ScheduledThreadPoolExecutor
or javax.swing.Timer. If you start by writing your own sleep() calls, without first investigating the higher-level objects, then you may be re-inventing a wheel.

What happens, when two threads try to access a synchronous block?

What happens, when two threads try to access a synchronized block?
Will one of the threads be queued somewhere and access the thread later, or will the thread give up if the trial fails?
Assuming you mean a synchronized block, one thread will manage to acquire the monitor, and the other thread will block until the monitor is released.
See section 14.19 and section 17.1 of the JLS for more details, including:
The synchronized statement (§14.19) computes a reference to an object; it then attempts to perform a lock action on that object's monitor and does not proceed further until the lock action has successfully completed. After the lock action has been performed, the body of the synchronized statement is executed. If execution of the body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.
(Emphasis mine.)
If you need any other semantics - e.g. timeouts - you should use one of the the types in the java.util.concurrent.locks package, so that you can use methods such as tryLock() and tryLock(long time, TimeUnit unit).
Will one of the threads be queued somewhere
Yes, It's queued in JVM and waits until runnig thread frees the lock.
will the thread give up if the trial fails
No, it keeps on trying till JVM is alive. but not trying during while another thread in running the synchronized code.(unless a timeout is specified)
Lets say ThreadA and ThreadB are trying for a synchronized block sb and ThreadB succeeds. Now, ThreadA will wait till ThreadB finishes. in the mean time, suppose ThreadC comes for sb. it sees that the block is being run by some thread and waits in same queue with ThreadA. When ThreadB finishes either ThreadA or ThreadC is given a chance to execute.
So, technically, it's NOT a queue but a similar datastructure.
One of them will wait, forever if necessary (such as the first thread executing an infinite loop), though that would be a rather bad design. There are no timeouts on code execution synchronisation.
From the JLS:
A synchronized statement acquires a mutual-exclusion lock on behalf of the executing thread, executes a block, then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock.
If synchronized block is being executed by another thread then both thread will wait. Otherwise , one thread will be allowed to work upon and another will wait until first thread completes its job.

Directed notifyAll()

A question if I may.
Lets suppose that my main thread creates 3 threads.
These 3 threads call wait() on a certain object.
Then the main thread calls notifyAll() for the same object.
How can I ensure than thread2, and only thread2, proceeds while thread1 and thread3 simply ignore the notification and go back to waiting state?
In essence, how can I direct my notification to a chosen thread?
If I am not mistaken, this would be quite simple to do in java 5. One would create different conditions and have the main thread only meet the condition on which thread2 is waiting.
However, how would I solve it in pre5?
Cheers,
Vic
You should note that threads can spontaneous wake even without a notify. So you always need some kind of condition. The general form of the code is:
synchronized (lockObj) {
while (!condition) {
lockObj.wait();
}
}
There can be performance reasons to only wake threads doing specific operations. For that look into java.util.concurrent.locks, but note that it is a performance issue not a doing-the-right-thing issue.

Categories