Is signal guaranteed to reach thread? - java

Lets say I have three threads, T1, T2, T3, a Lock lock and some Condition cond on a Resource resource.
T1 acquires lock and now does cond.await() due to some condition and T2 gets that lock and does cond.signal() and then proceeds to do lock.unlock(), but for a while, T3 was also trying to acquire the lock so it is at the line of lock.lock(), what exactly happens?
Does T2 re-get the lock or does T3 get it or is it random based on scheudler?

If you read the documentation, i.e. the javadoc of ReentrantLock, it specifically answers this question in the 3rd paragraph:
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.

Whenever a signal is issued one of the waiting threads will be removed and will be put back in entry set so that he can get a chance to run. In terms of signalAll all the waiting threads will be removed from the wait set and put back in entry set so that they get chance to run.
And yes the scheduler then decides which thread to pick from the entry set. In terms of fairness longest waiting will get the chance first.
Good explanation here

Related

Java Locks and Conditions

Say I have three threads, thread 1, thread 2, and thread 3 all sharing the same lock. Thread 2 acquires the lock, does some work and then blocks via a call to the await method. Thread 1 then acquires the lock, does some work, and during the middle of it, thread 3 tries to acquire the lock but is blocked since thread 1 is holding it. Thread 1 finishes working and, before terminating, signals thread 2 that it can reacquire the lock. So what happens then? Will thread 2 or thread 3 acquire the lock next?
Thank you so much for your time and help in advance.
If no priority is given, whoever comes first will acquire the lock.
While mutual exclusion may provide safety property, it does not ensure liveness property. There can be cases where a thread keeps coming first to acquire the lock, resulting in starvation (other threads wait forever because someone keeps occupying).
Google with the keywords highlighted will help you understand more. I found these slides really comprehensive http://www.cs.cornell.edu/Courses/cs414/2004su/slides/05_schedule.pdf
If you're using a ReentrantLock (or any of its subclasses), you can pass a "fairness" flag to the constructor. If set to true, this will ensure that control of the lock passes to the longest-waiting thread, in this case your Thread 1.
Lock lock = new ReentrantLock(true);

Signalling threads in a lock's condition

I have taken the following points from this API and I would like to know the difference between the 2 following points:
Waiting threads are signalled in FIFO order.
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.
It is related to Condition class which is usually returned by the ReentrantLock method .newCondition(), and the bit I quoted it's explaining the difference between the methods of Condition and the regular monitor methods of the Object class.
"Waiting threads are signalled in FIFO order". I think that as long as a lock is created either fair or not, the fact that the waiting threads are signalled in a FIFO order is totally irrelevant isn'it? because anyhow it's whether they have been constructed, fair or not, which decides how they are queued.
Just asking for a confirmation.
Thanks in advance.
Please see below answers to your questions:
1.Waiting threads are signalled in FIFO order.
When we invoke await() method of Condition, thread goes into waiting state, the above statement refers to how these threads in waiting state are signalled. So if threads T1 went to waiting state before T2, T1 will be signalled before T2.
2.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.
In continuation to above statement, when waiting thread is signalled, it tend to reaquire lock. Though above statement says T1 will be signalled before T2, but when it comes to reaquiring lock, the order of reacquisition uses concepts defined by Lock. So, it depends on how Lock object was created. While creating Lock you might have specified a fairness parameter:
ReentrantLock(boolean fair)
If yes then that parameter is used, if not then default behaviour of locks happens, you can read more on ReentrantLock Locks at this link
There could be more explanations to these statements, just tried to best detail my understanding here. Hoping was able to clarify.
Cheers !!
As long as a lock is created either fair or not, the fact that the waiting threads are signaled in a FIFO order is totally irrelevant, isn't it? Because anyhow it's whether they have been constructed, fair or not, which decides how they are queued.
I think it is relevant.
Consider a scenario where T1 and T2 are waiting on a condition C (with T1 waiting longer than T2), T3 is running inside the monitor and T4 is waiting for its initial lock acquisition. T3 signals C and leaves the monitor releasing the lock. Let's suppose no spurious wakeup occur.
If the lock is fair, T4 will definitely acquire the lock before T1, but the fact that waiting threads are signaled in FIFO order will guarantee you that T1 will acquire the lock before T2.
Also, if the lock is not fair, we can't say which thread will acquire the lock first between T1 and T4, but again the fact that waiting threads are signaled in FIFO order guarantees that T1 will acquire the lock before T2, provided no other signals occur until T1 acquires the lock (for example in case T1 is responsible for the next signaling).
I think the source code can give us more clues about how it works.ReentrantLock.newCondition() return a ConditionObject in AbstractQueuedSynchronizer.Here is the source code link AQS source code.
1.Waiting threads are signalled in FIFO order.
There are two queues in AbstractQueuedSynchronizer.
One is for waiting for the lock(just call it lock waiting queue),you will see two volatile variable head and tail in
AbstractQueuedSynchronizer's class definition,and the fairness parameter will affect this queue's behavior.When you new a fair ReentrantLock and call acquire,AQS will call FairSync's tryAcquire to check if current thread is the first thread waiting in the lock waiting queue,see hasQueuedPredecessors.
Another queue is the signal queue in the definition of ConditionObject,you will see two variable firstWaiter and lastWaiter.When await is called,a node will add to the tail of the queue and When signal is called,a node from the head will be dequeued and add to the lock waiting queue to reacquire the lock.Add to the lock waiting queue didn't mean it will be woke up,but a Lock.unlock() will be called after signal,which will wake up the waiters,see unparkSuccessor.
2.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.
wake up from the await method didn't mean to hold the lock,it will call acquireQueued to reacquire the lock and could be parked again.
In my understanding,the order of initially acquiring the lock is the same as the order of calling await,so the same as the order of calling acquireQueued,What confused me was but for fair locks favors those threads that have been waiting the longest.,When wake up from the await,in my opinion,it will be the first thread in the lock waiting queue,When call acquireQueued and check p == head && tryAcquire(arg),lock fair or not has no effect.
Hope this helps and let me if I am wrong.

Concurrency: Condition.awaitNanos() not releasing lock

In my program i am using a Condition object created from a
private static final Lock lock = new ReentrantLock();
like so:
private static final Condition operationFinished = MyClass.lock.newCondition();
Occasionally (as it is always happening with concurrency problems) i encounter following behavior:
Thread1 aquires the lock
Thread1 calls operationFinished.awaitNanos() - this should suspend Thread1 and release the lock.
Thread2 tries to aquire the same lock, but debugging output shows that Thread1 is still holding the lock!
According to documentation this behavior is impossible, because upon awaitNanos() Thread1 first releases the lock and then suspends.
If it didn't release the lock, then it would not suspend, therefore Thread2 could never even get a possibility to try to get hold on the lock.
Has anybody experienced something similar? This errors happens once in 100 times - but still it indicates that I am either not using the concurrency-utilities in a proper way, or that there is some kind of bug in the java.utils.concurrent.* package (which i doubt).
UPDATE:
In response to Peters answer:
I observe following behavior: Apparently the 2 threads deadlock each other. I can see that Thread2 blocks (waiting for the lock) and at the same time awaitNanos() in Thread1 never times out.
Are you sure that the wait time hasn't finished? If you wait for a short period of time (a few hundred nanoseconds, for example), the wait time could expire before Thread2 can fully start, in which case Thread1 might be reactivated first.
Depending on how you are viewing this information, I have seen many examples of where multiple threads wait() on an object still say they are all holding the same lock. It may be that the stack trace or monitoring is mis-leading.
Say you have thread1 which is holding the lock, but in awaitNanos(), you have Thread2 which is trying to obtain the lock(), but sometimes Thread3 is holding the lock as well....
I would do a jstack -l {pid} to check all the threads which might be holding the lock.
If a lock deadlocks, awaitLock (nor wait()) won't return as it must acquire the lock before doing so. (Unless it is interrupted)

Locks in java class

suppose we have this next sample code:
while(some condition){
lock1.lock();
.
.
}
the question is:
suppose the condition of the while loop is exiting for some thread that run's over this code part and lock1 is available, is it possible that the thread will check the condition of the loop but still won't get the lock?
or is it guaranteed in this case that if the condition is checked the thread gets the lock?
In short: Yes, it is possible.
If another thread has already acquired the lock, then your thread will be forced to wait for it to become free.
Remember that you have no way of knowing how two or more concurrently executing threads interleave their instruction executions. Assume two threads, A and B, execute this code. If thread A finds the condition true, it is possible that it gets preempted (taken off the CPU by the OS scheduler) before actually acquiring the lock (that is, between evaluating the while condition and the call to lock()), so thread B also finds the condition true, takes the lock and thread A is left waiting.
You shouldn't base your lock on a condition modifiable by other threads, where such condition may affect code inside the lock. There's no guarantee that the condition won't change before you acquire the lock.

What is ReentrantLock#tryLock(long,TimeUnit) doing when it tries to aquire the lock?

What is the ReentrantLock#tryLock(long,TimeUnit) implementation doing when it tries to aquire a lock ? Assume Thread A acually owns the Lock of myLock, and Thread B call myLock.tryLock(10,SECONDS), is Thread B sleeping or waiting ?
In other words, was is the difference of this 2 implementations:
1.
while (true)
try {
if (readLock.tryLock())
return;
MILLISECONDS.sleep(5);
}catch (InterruptedException e) {}
2.
while (true)
try {
if (readLock.tryLock(5,MILLISECONDS))
return;
}catch (InterruptedException e) {}
First of all, the second will wait less than 5 millis if lock released, because it doesn't need wait for wake up from the sleep. So, it's less exposed to starvation problem.
Then, j.u.c.l package uses LockSupport#park methods to pause a thread, not Thread.sleep. And as I understand it makes difference on the thread scheduler, the park allows lower latency, but not sure how exactly the sleep is implemented.
Also, your code doesn't make any sense, exactly the same effect could be achieved by lock() method.
It is waiting for the lock and the thread is asleep.
Internally, if the tryLock(long, TimeUnit) method fails to acquire the lock immediately, it waits for the amount of time specified. If the lock becomes available before this amount of time, it returns immediately with the lock. Note that in this case, when there are multiple threads requesting a lock, the ReentrantLock will randomly pick a thread to give the lock to next. This behavior can be changed by passing true to the fairness value in the constructor new ReentrantLock(true).
The second example will only check for the lock every five milliseconds. If the lock becomes available while it is sleeping and is given to another thread before it wakes up, this thread will be unavailable for acquiring the lock.
If you're using this code with many threads waiting for the lock, note that neither solution you have provided will guarantee that every thread will get the lock at some point. The second code can continue getting sniped by another thread just before the five milliseconds are up. The first code is random, but even with the fairness value set each thread will give up its place in line every five milliseconds. If this is the case you're better off increasing the timeout value. A good value would be about double the maximum amount of time that you would expect it to take for every thread to get a turn.
Technically there is no difference with respect to the state of the waiting thread. From the JavaDoc:
If the lock is held by another thread then the current thread becomes disabled
for thread scheduling purposes and lies dormant [...]
This is very similar to what happens in case of sleeping, but I guess we can't say for sure unless we know the implementation.
Now, note this part:
[...] lies dormant until one of three things happens:
The lock is acquired by the current thread; or [...]
That means that in case the lock becomes free in the meantime, it will acquire it and return. In the other case, while it is sleeping, the thread has no chance to get the lock even if it is free.
Another subtle difference that may appear between the two cases is the fact that the timed trylock is sensitive to the fairness policy of the ReentrantLock. That is:
If this lock has been set to use a fair ordering policy then an available lock
will not be acquired if any other threads are waiting for the lock.
The untimed trylock is known to be not fair and may succeed to acquire the lock even if other threads are already waiting on it.
I guess that the second one will wait for a 5 milliseconds to get a lock in difference with the first one which will try to lock immediately. So thread B will wait if in 5 ms (within 5ms) lock it doesn't get a lock it will return false. Normally there no difference if you have 5ms in your timeout but in case you increment this number you will get the clear image.
5ms is a timeout it will wait for 5ms for a lock that means if the lock is available after 3ms it will return after 3 ms with true.
For a great reference on how locks and other concurrency primitives are implemented see Shavit and Herlihy's excellent The Art of Multiprocessor Programming.

Categories

Resources