ReenTrantLock structure

FIG. 1-1

ReenTrantLock inherits the Lock interface. The Lock interface is declared as follows:

The method name instructions An exception is thrown
The lock () Block until the lock is acquired successfully There is no
LockInterruptibly () Attempts to acquire the lock until either the lock is acquired or the thread is interrupted InterruptedException
TryLock () Attempts to acquire a free lock, return true on success, false on failure, will not block, return immediately There is no
tryLock(long time, TimeUnit unit) An attempt is made to acquire an idle lock within time, which can be interrupted during waiting time InterruptedException
Unlock () Release the lock There is no
newCondition() Returns an instance of condition of the current lock for conditional wait There is no

ReentrantLock is the implementation of Lock

1. Partial methods of ReentrantLock

Figure 2-1

  • According to the figure 2-1 can know the Sync object provides all the realization mechanism of the Sync inherited AbstractQueuedSynchronizer
  • NonfairSync unfair lock that inherits Sync
  • FairSync inherits Sync for fair synchronization

1. Sync


Sync is a parent of NonfairSync and FairSync.

/* / abstract void lock(); /** * Final Boolean nonfairTryAcquire(int acquires) {final Thread current = thread.currentThread (); int c = getState(); // The parent synchronizer method, which gets the current synchronization status, will be analyzed in future articlesif(c == 0) {// A state equal to 0 indicates that no lock was acquiredif(compareAndSetState(0, acquires)) {// Modify state in CAS modesetExclusiveOwnerThread(current); // Set the current thread as the owner of the lockreturn true; }}else ifInt nexTC = c + acquires; (current == getExclusiveOwnerThread()) {int nexTC = c + acquires; // Get the lock counterif(nextc < 0) // overflow //"Maximum lock count exceeded");
              setState(nextc); // Set the counter to the status valuereturn true;
          }
          return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; // Release lock, synchronization state minus int valueif(Thread.currentThread() ! = getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); Throw the Boolean free = exception if the current phase is not the owner of the lockfalse;
          if(c == 0) {// If the synchronization status value is 0, the lock is released successfullytrue; 
              setExclusiveOwnerThread(null); // Set the thread owning the lock to null}setState(c); // Reassign the synchronization statusreturnfree; } // Determine if the current thread is locked to protected final BooleanisHeldExclusively() {
        
          returngetExclusiveOwnerThread() == Thread.currentThread(); } // Return the locked ConditionObject instance final ConditionObjectnewCondition() {
          returnnew ConditionObject(); } // Methods relayed from outer classgetOwner() {
          returngetState() == 0 ? null : getExclusiveOwnerThread(); } // Get the current lock count final intgetHoldCount() {
          returnisHeldExclusively() ? getState() : 0; } // Determine whether the lock is obtained. Final BooleanisLocked() {
          returngetState() ! = 0; // The lock is not equal to 0}Copy the code

2. NonfairSync Unfair lock


 static final class NonfairSync extends Sync {
       private static final long serialVersionUID = 7316153563782823691L;

       /**
        * Performs lock.  Try immediate barge, backing up to normal
        * acquire on failure.
        */
       final void lock() {
           if(compareAndSetState(0, 1)setExclusiveOwnerThread(Thread.currentThread());
           else
               acquire(1);
       }

       protected final boolean tryAcquire(int acquires) {
           returnnonfairTryAcquire(acquires); }}Copy the code
  • According to the source code found that unfair lock inherits Sync parent class, because there is no fair and unfair lock release, so fair lock and unfair lock only achieve their own lock logic. According to unfair lock source code found, its internal only implementedThe lock ()andTryAcquire (int acquires)Method, where andTryAcquire (int acquires)Method directly calls the parent class’sNonfairTryAcquire (acquires)The parent class has been resolved in Sync. According to lock source code discovery, start to determine whether it is the first time to obtain the lock, if the lock is successfully obtained, the current thread is set as the owner of the lock, otherwise call the parent classAcquire (1)Methods (described in the next introduction to synchronizers).

3. FairSync Fair lock


static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; /** Call acquire () */ final voidlock() { acquire(1); } /** * protected final Boolean tryAcquire(int acquires) {final Thread current = thread.currentThread (); int c = getState();if (c == 0) {
                if(! hasQueuedPredecessors() && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);
                    return true; }}else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false; }}Copy the code
  • According to the above code, it is found that the acquisition code of the fair lock and the acquisition code of the unfair lock are very familiar, and there is only one more fair lock! hasQueuedPredecessors()Judgment, in fact, this method is to determine whether there is a thread than the current thread to wait for the longest time, if not, then try to acquire locks, after successful sets the current thread to lock the occupant, so fair and unfair is whether according to the time of waiting to get the lock, dining hall, for example, to line up one by one, this is fair, if someone cut in line, It’s just not fair.

3. ReentrantLock Other methods


 public ReentrantLock() {
        sync = new NonfairSync();
    }
public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
  public void lock() {
        sync.lock();
    }
 public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
public boolean tryLock() {
        returnsync.nonfairTryAcquire(1); Public Boolean tryLock(long timeout, TimeUnit Unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
 public Condition newCondition() {
        return sync.newCondition();
    }
public int getHoldCount() {
        return sync.getHoldCount();
    }
  public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }
 public final boolean isFair() {
        return sync instanceof FairSync;
    }
protected Thread getOwner() {
        return sync.getOwner();
    }
public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
  public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }
public final int getQueueLength() {
        return sync.getQueueLength();
    }
protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }
 public boolean hasWaiters(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if(! (condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
    }
   public int getWaitQueueLength(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if(! (condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
    }
    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if(! (condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

Copy the code
  • In fact, according to the above source code found, whether the implementation of LOCK interface method, or the subsequent new method, its implementation functions rely on an object, that issyncIn the introductionsyncAs I said, it’s inheritanceAbstractQueuedSynchronizerSynchronizer, many of which call methods directly from the parent synchronizer, will be highlighted in the next article, Java Lock ReentrantLock (2)AbstractQueuedSynchronizerSynchronizer source, analysis synchronizer is how to rely on THE FIFO queue to complete the lock mechanism.

Third, summary

  • ReentrantLock implements the LOCK interface
  • ReentrantLock enables fair and unfair lock acquisition
  • ReentrantLock can be used to obtain a lock within a timeout period
  • ReentrantLock allows conditional wait and wake up
  • ReentrantLock can retrieve lock response interrupts