Question

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) {}
Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top