I scanned all the java documentation on the synchronized statements looking for an answer to this question with no luck.
Say I have thread1, thread2, thread3 trying to run the following code all at the same time.
synchronized(lockObj) {
doSomething();
}
Assume thread1 gets first to doSomething(), thread2 then thread3 which will block and wait on the synchronized statement.
Question
When thread1 releases the lock, which of the threads will be released first?
What is the general order rule that applies when releasing a lock?
1. Either thread2 or thread3. There is no guarantee:
Likewise, no assumptions should be made about the order in which threads are granted ownership of a monitor or the order in which threads wake in response to the notify or notifyAll method
http://docs.oracle.com/javase/1.5.0/docs/guide/vm/thread-priorities.html#general
2. Java monitors (synchronized/await/notify/notifyAll) are non-fair. The synchronization primitives from java 1.5 usually have parameters to enforce the fairness. Be advised that the fair version have a considerably performance penalty, usually the non-fair version should work be used: statistically, every thread will be given the chance to run, even if the order is not strictly enforced.
Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower; often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee lack of starvation. Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. Also note that the untimed tryLock method does not honor the fairness setting. It will succeed if the lock is available even if other threads are waiting.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html#ReentrantLock%28boolean%29
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.
ReentrantLock API doc says:
The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favor granting access to the longest-waiting thread.
Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock.
I am not able to understand points 2:
If one thread obtain lock multiple times in succession, then as per point 1, other threads will wait for longer and that does mean they will get the lock next time. Then how this does not affect (fairness of) thread scheduling? Thus, I feel fair lock is nothing but longest waiting time first thread scheduling.
I think they're just trying to separate the fairness logic side from the scheduling logic. Threads may be concurrent, but that doesn't mean they try to access Locks simultaneously. Thread priority requests are only 'hints' to the OS, and are never guaranteed the way they may be expected.
So, just because you have threads A and B, which may request a lock, which may even have identical behavior, one thread may execute, acquire the lock, release, re-acquire, before the other locks even request it:
A: Request Lock -> Release Lock -> Request Lock Again (Succeeds)
B: Request Lock (Denied)...
----------------------- Time --------------------------------->
Thread scheduling logic is decoupled from the Lock logic.
There are other scheduling issues too, the burden of which often falls on the software designer, see Starvation and Livelock
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.
private static void WaitInQueue(Customer c)
{
synchronized(mutex){
//Do some operation here.
}
}
I need to make threads wait before proceeding(only one at a time), however, it appears that synchronized is not using FIFO to determine which should proceed next.(It seems like LIFO) Why is this?
How can I ensure that the first thread to wait at synchronized will be the first one to aquire the lock next?
a synchronized block makes no guarantees about fairness - any of the waiting threads may in theory be chosen to execute. if you really want a fair lock (fifo), switch to use the newer locking mechanisms introduced in java 5+.
see for example the documentation for ReentrantLock.
here's how you'd use a fair lock:
private final ReentrantLock lock = new ReentrantLock(true); //fair lock
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
note, however, that this results in overall degraded performance and so is not recommended.
quoting from the documentation"
The constructor for this class accepts an optional fairness parameter.
When set true, under contention, locks favor granting access to the
longest-waiting thread. Otherwise this lock does not guarantee any
particular access order. Programs using fair locks accessed by many
threads may display lower overall throughput (i.e., are slower; often
much slower) than those using the default setting
You can use the Semaphore class, with a fairness setting set to true and a count of 1. This guarantees FIFO order for threads, and is almost identical to having a synchronized block.
ReentrantLock also provides a fairness setting.
To answer "Why is this?": There's rarely any reason to use a specific order on a lock. The threads hit the lock in random order and may as well leave it the same way. The important thing from the JVM's viewpoint is to keep the cores busy working on your program's code. Generally, if you care about what order your threads run in you need something a lot fancier than a lock or semaphore.
The only good exception I can think of is if your lock always has waiting threads, creating the real possibility that a thread that hits it might wait for many seconds, continually getting bumped to the back of the "queue", while an irate user fumes. Then, FIFO makes a lot of sense. But even here you might want to spend some time trying to speed up the synchronized block (or avoiding it completely) so most threads that hit it don't get blocked.
In summary, think long and hard about your design if you find yourself worrying about the order your threads run in.
You should use Thread.join for wait before proceeding.
Just go through the following link
http://msdn.microsoft.com/en-us/library/dsw9f9ts(v=vs.90).aspx
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.