AQS

AbstractQueuedSynchronizer
Copy the code

concerns

Node
A first-in, first-out queueCopy the code
volatile int state
Marks whether or how many times the current lock has been acquired (reentrant lock)Copy the code
tryAcquire()
Exclusive lock uses an attempt to acquire lock method that needs to be subclass overriddenCopy the code
tryRelease()
The attempt to release lock method used by exclusive locks needs to be subclass overriddenCopy the code
tryAcquireShared()
The shared lock uses an attempt to acquire lock method that needs to be subclassedCopy the code
tryReleaseShared()
The attempt to release lock method used by the shared lock needs to be subclassedCopy the code

ReentrantLock

There is a member variable Sync Sync implements AQS interface 1. 2. AQS synchronizer is usedCopy the code

The sample code

	private Lock lock = new ReentrantLock();

	public void method(a) {

		lock.lock();

		try {

			Thread.sleep(1000);
			System.out.println("hello");

		} catch (Exception e) {
			e.printStackTrace();
		} finally{ lock.unlock(); }}Copy the code

ReentrantLock constructor

public ReentrantLock(a) {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

/* We can see from the above two constructors that it is possible to create different synchronizers depending on the constructor we choose or the arguments we pass. NonfairSync is unfair. FairSync is fair

Copy the code

lock()

// Call the lock method of different synchronizers according to different synchronizers
public void lock(a) {
    sync.lock();
}
Copy the code
FairSync.lock()
final void lock(a) {
	// This method is a parent of AQS
    acquire(1);
}

public final void acquire(int arg) {
	// The tryAcquire method should be subclassed
    // Call the fairsync.tryacquire method because the current class is FairSync
    // If tryacquire returns true, the && expression is not executed
    If the tryAcqyire method returns false, it fails to acquire the lock, enters the wait queue and performs selfInterrupt to interrupt the current thread
    if(! tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }/ / Java. Util. Concurrent. The locks. Already. FairSync. TryAcquire (int), the parameter value is 1
protected final boolean tryAcquire(int acquires) {
		// Get the current thread
        final Thread current = Thread.currentThread();
        // Get the value of aqs. state, which is used to determine whether a thread has acquired the lock
        int c = getState();
        // If the value is 0, no thread has acquired the lock
        if (c == 0) {
        	The hasqueuedToraise method determines whether a waiting thread exists on the wait queue (because it is a fair lock)
            //compareAndSetState Specifies the state value for the CAS operation
            / / setExclusiveOwnerThread set the current thread of acquiring a lock for the current thread
           	// So this expression in if means:
            If the CAS operation succeeded and the set thread succeeded, true is returned indicating that the lock was obtained
            if(! hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true; }}// If the value of state is not 0, there are threads competing for the lock
        // Determine whether the thread that acquired the lock is current (reentrant lock)
        else if (current == getExclusiveOwnerThread()) {
        	// If state is accumulated, it represents the number of reentrant times
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }


Copy the code
NonfairSync.lock()
final void lock(a) {
		// Just try to get the lock (set state). This is the difference from a fair lock
      if (compareAndSetState(0.1))
      		// If so, set the exclusive thread to the current thread
          setExclusiveOwnerThread(Thread.currentThread());
      else
      		// if not successful, call AQS acquire method, which mentioned above to tryAcquire directly
          acquire(1);
  }
  
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}


// This method is basically the same as a fair synchronizer, the only difference is one line less
//hasQueuedPredecessors
// In other words, it is not fair to preempt the lock without determining whether there are waiting threads in the queue
// There are two places where an unfair lock preempts the lock directly, once in the lock method and once in the current method
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;
}
  
  

Copy the code

unlock()

Either a fair lock or an unfair lock is one way to do itCopy the code
public void unlock(a) {
    sync.release(1);
}

// This is AQS release method
public final boolean release(int arg) {
	// The tryRelease method that subclasses are required to implement, indicating whether to release the lock public
      if (tryRelease(arg)) {
          Node h = head;
          if(h ! =null&& h.waitStatus ! =0)
          		// If the lock is released successfully and there are values in the wait queue
                // Wake up a thread
              unparkSuccessor(h);
          return true;
      }
      return false;
  }
  
  
protected final boolean tryRelease(int releases) {
		// The value of state is -1
      int c = getState() - releases;
      // An error is reported if the thread releasing the lock is different from the thread holding the lock
      if(Thread.currentThread() ! = getExclusiveOwnerThread())throw new IllegalMonitorStateException();
      boolean free = false;
      // If state is 0, the lock is released successfully
      if (c == 0) {
          free = true;
          // Set the exclusive thread to NULL
          setExclusiveOwnerThread(null);
      }
      setState(c);
      return free;
  }

Copy the code