How the lock () method works in the java file ReentrantLock

I am trying to understand how ReentrantLock works in java.

Consider a simple example below:

private ReentrantLock lock; public void foo() { lock.lock(); try{ ... }finally { lock.unlock(); } } 

I tried to figure out the hierarchy of calls to the lock () method.

 public void lock() { sync.lock(); } 

For FairSync:

 final void lock() { acquire(1); } 

For NonFairSync:

 final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } 

Both lock () methods call get () with an argument of 1.

In the AbstractQueuedSynchronizer class:

 public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } static void selfInterrupt() { Thread.currentThread().interrupt(); } 

If the current thread cannot receive the resource (i.e. some other thread has acquired this resource), then the current thread must wait. In this case, the ReentrantLock calls the selfInterrupt () method.

Now my question is, how can the interrupt () method stop the thread, which is equivalent to the wait () method in synchronization?

Also, after a resource has been released by another thread, how does currentThread start automatically? (After calling the unlock () method by another thread that internally calls sync.release(1); )

I also tried to figure out how the interrupt () method works from here , but could not find the answer to my questions.

+6
source share
1 answer

If the current thread cannot receive the resource (i.e. some other thread has acquired this resource), then the current thread must wait. In this case, the ReentrantLock calls the selfInterrupt() method.

No, if tryAcquire returns false , acquireQueued will be called. Inside this method, LockSupport#park is used to unlock the stream. Javadoc state

If permission is available, it is consumed and the call returns immediately; otherwise, the current thread is turned off for the flow planning and false while one of three things happens:
- [..]
- Some other threads interrupt the current thread;

In this case, it does not actually throw an InterruptedException , the method simply returns. To verify that the corresponding thread was called due to an interrupt, it should use Thread#interrupted() , which returns true or false depending on which, but also clears the interrupt flag from the corresponding Thread instance .

So, acquireQueued passes this aborted value and allows you to acquire reset the interrupt flag to Thread , if necessary in this small piece of code

 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); 

Also, after a resource has been released by another thread, how does currentThread start automatically?

Again, it uses LockSupport utility with unpark

Makes the permission available for this stream, if it was not already available. If the flow is blocked in the park, it will be unlocked.

+1
source

All Articles