I am under the impression that most people use only the jvm implementation given by the Oracle (originally from Sun microsystems). Correct me if I am wrong.
When I went through the API for notify(), it says :
Wakes up a single thread that is waiting on this object's monitor. If
any threads are waiting on this object, one of them is chosen to be
awakened. The choice is arbitrary and occurs at the discretion of
the implementation.
I would like to know in what order the waiting threads will be invoked when notify() is called in the Oracle's jvm.
You might wonder why I am not considering to use notifyAll() and just stop worrying. But why should I invoke all the waiting threads unnecessarily when I can do with invoking just one thread with notify()? Even if I use notifyAll(), I have no control which of the waiting threads will get the monitor.
Oracle should have documented how it is implemented in its own implementation right in the api link given above.
The order of execution with Threads is undefined.
If you write any code based on the assumption that you can predict the order of execution, it will run on a single machine at best. So how Oracle actually implemented it is - except for a research case - irrelevant, as it probably is implemented differently on the next machine and even on the next version of the Oracle JVM.
If you need a more fine-grain control, then you need to adjust your architecture and use the classes from the concurrent package in a proper way. Synchronized/wait/notify is just a very basic "brute-force" implementation of thread-synchronization with many pit-falls and restrictions.
You can rely only on what API says and API does not guarantee any specific order. If you need threads to wake up in a certain order use ReentrantLock in fair mode then this lock's Condition.signal() will wake the thread waiting for this Condition longest.
You can use ReentrantLock(boolean fair) with fairness flag in constructor. Conditions created from a such lock are also fair:
Creates an instance of ReentrantLock with the given fairness policy.
and
The ordering of lock reacquisition for threads returning from waiting
methods is the same as for threads initially acquiring the lock, which
is in the default case not specified, but for fair locks favors those
threads that have been waiting the longest.
Related
The way Lock interface with class Reentrant(true) lock works is that it uses BlockingQueue to store Threads that want to acquire the lock. In that way thread that 'came first, go out first'-FIFO. All clear about that.
But where do 'unfair locks' go, or ReentrantLock(false). What is their internal implementation? How does OS decide which thread now to pick? And most importantly are now these threads also stored in a queue or where? (they must be somewhere)
The class ReentrantLock does not use a BlockingQueue. It uses a non-public subclass of AbstractQueuedSynchronizer behind the scenes.
The AbstractQueuedSynchronizer class, as its documentation states, maintains “a first-in-first-out (FIFO) wait queue”. This data structure is the same for fair and unfair locks. The unfairness doesn’t imply that the lock would change the order of enqueued waiting threads, as there would be no advantage in doing that.
The key difference is that an unfair lock allows a lock attempt to succeed immediately when the lock just has been released, even when there are other threads waiting for the lock for a longer time. In that scenario, the queue is not even involved for the overtaking thread. This is more efficient than adding the current thread to the queue and putting it into the wait state while removing the longest waiting thread from the queue and changing its state to “runnable”.
When the lock is not available by the time, a thread tries to acquire it, the thread will be added to the queue and at this point, there is no difference between fair and unfair locks for it (except that other threads may overtake it without getting enqueued). Since the order has not been specified for an unfair lock, it could use a LIFO data structure behind the scenes, but it’s obviously simpler to have just one implementation code for both.
For synchronized, on the other hand, which does not support fair acquisition, there are some JVM implementations using a LIFO structure. This may change from one version to another (or even with the same, as a side effect of some JVM options or environmental aspects).
Another interesting point in this regard, is that the parameterless tryLock() of the ReentrantLock implementation will be unfair, even when the lock is otherwise in fair mode. This demonstrates that being unfair is not a property of the waiting queue here, but the treatment of the arriving thread that makes a new lock attempt.
Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This "barging" behavior can be useful in certain circumstances, even though it breaks fairness.
Do mutex locks ensure bounded waiting condition ? Is it possible if two threads are trying to get hold of a lock, but only one process (just by luck) gets it again and again. Since Peterson's Algorithm ensures bounded waiting, is it better to use that instead of mutex locks ?
It is possible to have unbounded wait with mutices, if for instance locking attempts keep coming in on a mutex, at least in C++ std::mutex there's no guaranteed first comes first gets.
However this shouldn't really be a concern - Unless you have some lock with many many threads locking all the time (and even in that case it's very unlikely to cause some starvation situation).
The best thing to do is always use standard library locking mechanism and not write your own mutices.
Mutex with "bounded waiting condition" is called Fair sometimes. As gbehar correctly mention above, C++ standard doesn't define fairness for std::mutex. If you really need fair mutex, you can look at Intel TBB, where fairness is guaranteed for some kinds of them. I would like to remember that fairness comes not without overhead.
See https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Mutex_Flavors.html for details.
Update: Current link https://github.com/oneapi-src/oneTBB/blob/master/doc/main/tbb_userguide/Mutex_Flavors.rst
I am trying to understand the usefulness of fairness property in Semaphore class.
Specifically to quote the Javadoc mentions that:
Generally, semaphores used to control resource access should be initialized as fair, to ensure that no thread is starved out from accessing a resource. When using semaphores for other kinds of synchronization control, the throughput advantages of non-fair ordering often outweigh fairness considerations.
Could someone provide an example where barging might be desired here. I cannot think past resource access use case. Also, why is that the default is non-fair behavior?
Lastly, are there any performance implications in using the fairness behavior?
Java's built-in concurrency constructs (synchronized, wait(), notify(),...) do not specify which thread should be freed when a lock is released. It is up to the JVM implementation to decide which algorithm to use.
Fairness gives you more control: when the lock is released, the thread with the longest wait time is given the lock (FIFO processing). Without fairness (and with a very bad algorithm) you might have a situation where a thread is always waiting for the lock because there is a continuous stream of other threads.
If the Semaphore is set to be fair, there's a small overhead because it needs to maintain a queue of all the threads waiting for the lock. Unless you're writing a high throughput/high performance/many cores application, you won't probably see the difference though!
Scenario where fairness is not needed
If you have N identical worker threads, it doesn't matter which one gets a task to execute
Scenario where fairness is needed
If you have N tasks queues, you don't want one queue to be waiting forever and never acquiring the lock.
Can someone explain the various differences between various synchronization methods in Java?
Syncornized blocks (like monitors?)
Locks - Java concurrent lock.lock()/lock.unlock()
Semaphores..?
Object.wait() & Object.notify() (like Mutex?)
Other classes
So really I wanted to know what are the different Java sync options commonly used and how they map to "traditional"/theoretical Mutexs, Semaphores, Locks, and Monitors.
Cheers!
I'll give a brief clarification of each:
synchronized blocks are your average critical section. Not much control is given. Only one thread may acquire the lock at one time and it will automatically release it when the synchronized scope ends.
locks are a more flexible version of the synchronized block. Depending on the implementation they may be reentrant or may support operations like tryLock which only attempts to take the lock if it's free, otherwise returns immediately. Locks need to be unlocked explicitly.
a semaphore is basically a lock but with the added feature that several threads may enter the critical section at one time. It operates on the more general notion of "permits", where a semaphore may have several permits available that threads want to acquire. A thread may take one or more permits and may restore one or more permits. It allows to think about synchronization more in terms of "available resources" than in terms of "code that needs to be protected".
wait / notify is roughly equivalent to the concept of condition variables. Similarly, they must be protected by a synchronized block and only work correctly if they are called when a lock is held on the object being used as a monitor.
Java has native support of threading and synchronization. The native (or low-level) way to synchronize threads is using synchronized blocks and methods ( == critical section), wait() and notify().
This technique allows you to do everything you want but unfortunately the way is sometimes pretty verbose.
Doug Lea developed the concurrency package initially under Apache project. Then this package was adopted by Sun Microsystems. This package provides more convenient API.
Take a look on this article for more details: http://docs.oracle.com/javase/tutorial/essential/concurrency/
This question is inspired by this other question.
If multiple threads are waiting on a synchronized block, and the lock becomes available, who goes first? Is it by thread priority (and then first-come-first-served)?
And do the same rules apply for notify (with multiple waiting threads)?
According to this guy: http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html
Java issues no guarantees about the sequence. So I guess it is not based on thread priority
I'll try to look further for an explanation on how Java actually decides who goes first.
Someone else mentioned the availability of fair locks. If you really care who goes first, then you may have a real-time problem. In that case, you can make use of RTSJ, wherein the ordering and other semantics of lock acquisition is specified. The specifics are available in the RTSJ Spec under Synchronization. Quoting from the rationale section:
Java's rules for synchronized code
provide a means for mutual exclusion
but do not prevent unbounded priority
inversions and thus are insufficient
for real-time applications. This
specification strengthens the
semantics for synchronized code by
mandating priority inversion control,
in particular by furnishing classes
for priority inheritance and priority
ceiling emulation. Priority
inheritance is more widely implemented
in real-time operating systems and
thus is required and is the initial
default mechanism in this
specification.
for your second Question
one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
From http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#notify()
It depends on thread priority and thread scheduling algorithm and also the lock on the synchronized block is not "fair". This means that if there are 2 waiting threads with the same priority and the first thread waited more than the second thread that doesn't necessarily mean that the first thread will be executed first.