Search code examples
javamultithreadingnonblockingreentrantlock

How does ReentrantLock.tryLock() works as it seems from source code that it does not use synchronized block or function


As I was using tryLock() method in one of my project, while using the same the question which is striking mind is that - tryLock() is said to be non blocking mechanism, how does it manages to get a lock without blocking.

There can be two scenario

  1. It is not using synchronized block/method internally, then the question is, how does it work in multi threaded environment
  2. It is using synchronized block/method internally, then the question is, how is it non blocking

In order to find the answer I have checked the below code for tryLock

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

And here goes the code for sync.nonfairTryAcquire(1) which actually gets the work done

 final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            int nextc = c + acquires;
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }

As it seems that the code for tryLock() does not use synchronized anywhere, how does it work in multi threaded environment?


Solution

  • how does it manages to get a lock without blocking?

    It doesn't always get the lock. That's the whole point: lock.tryLock() can fail when lock.lock() would have blocked the caller.

    it does not use synchronized block or function

    That would defeat the purpose. The point is not to block for any reason.

    I am not familiar with that code, but it looks like the lock actually is acquired (or not) in compareAndSetState(0, acquires). Probably there is a Compare and Set hardware instruction somewhere at the heart of it.

    FWIW, The AtomicInteger.compareAndSet(...) function does something very similar.