AQS---ReentrantLock

概述

  A reentrant mutual exclusion {@link Lock} with the same basic behavior and semantics as the implicit monitor lock accessed using {@code synchronized} methods and statements, but with extended capabilities.

    一个可重入的互斥Lock,和synchronized有相同的基本语义和行为,但有扩展能力;

 

  A {@code ReentrantLock} is <em>owned</em> by the thread last successfully locking, but not yet unlocking it. 

    ReentrantLock是线程自有的;

  A thread invoking {@code lock} will return, successfully acquiring the lock, when the lock is not owned by another thread. 

    当锁不被其他线程占用,一个线程调用Lock将会成功获得lock;

  The method will return immediately if the current thread already owns the lock. 

    如果当前线程已拥有Lock,将会立即return;

  This can be checked using methods {@link #isHeldByCurrentThread}, and {@link #getHoldCount}.

    可以使用isHeldByCurrentThread(),  getHoldCount() 检测Lock占用情况;  

 

  The constructor for this class accepts an optional <em>fairness</em> parameter.  

    构造器支持一个fairness参数;

  When set {@code true}, under contention, locks favor granting access to the longest-waiting thread.

    当构造器参数为true,为公平锁,优先等待时间最长的线程;

  Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower;  often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee lack of starvation.

    使用 公平锁 比 非公平锁 可能有较低的吞吐量,但在获得lock和保证无饥饿 差异较小;

  Note however, that fairness of locks does not guarantee fairness of thread scheduling.

    公平锁 不能保证线程调度的公平性;

  Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock.

    公平锁 可能导致 一个线程多次获得lock,而 其他线程获得不了lock;

 

  Also note that the untimed {@link #tryLock()} method does not honor the fairness setting. 

    注意:tryLock()无时间参数的 不遵守公平设置;

  

  It is recommended practice to <em>always</em> immediately follow a call to {@code lock} with a {@code try} block, most typically in a before/after construction such as:

    推荐 在调用lock() 后 跟随一个 try...finally...块:

    reentrantLock.lock();  

    try {

      // method body

    }finally{

      reentrantLock.unlock();

    }

  

  In addition to implementing the {@link Lock} interface, this class defines a number of {@code public} and {@code protected} methods for inspecting the state of the lock.  

    除了实现lock接口外,该类定义了大量的public、protected方法检测锁的状态;

  Some of these methods are only useful for instrumentation and monitoring.

    对监控有用;

  

  Serialization of this class behaves in the same way as built-in locks: a deserialized lock is in the unlocked state, regardless of its state when serialized.

    该类的序列化行为 和 内置锁一样,反序列化将忽略状态(反序列化lock是unlock状态);

    

  This lock supports a maximum of 2147483647 recursive locks by the same thread. Attempts to exceed this limit result in {@link Error} throws from locking methods.

    一个线程最大支持2147483647递归lock,超限制将会报error异常;

链路

lock()

// java.util.concurrent.locks.ReentrantLock.lock
    public void lock() {
        sync.lock();
    }

    // java.util.concurrent.locks.ReentrantLock.FairSync.lock    【公平获取锁】
    final void lock() {
        acquire(1);
    }

    // java.util.concurrent.locks.ReentrantLock.NonfairSync.lock    【非公平获取锁】
    final void lock() {
        // 如果直接获取锁成功 -> 设置当前线程独占
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        // 如果获取锁失败 -> 再次尝试获取锁 & 如果获取失败 -> 以独占模式加入队列
        else
            acquire(1);
    }

    // java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire
    /**
     * Acquires in exclusive mode
     */
    public final void acquire(int arg) {
        // 如果获取锁失败 && 以独占模式加入队列成功 -> 将当前线程中断
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    // java.util.concurrent.locks.ReentrantLock.FairSync.tryAcquire
    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;
    }

  

unlock()

// java.util.concurrent.locks.ReentrantLock.unlock
    public void unlock() {
        sync.release(1);
    }

    // java.util.concurrent.locks.AbstractQueuedSynchronizer.release
    /**
     * Releases in exclusive mode.
     */
    public final boolean release(int arg) {
        // 如果 以独占模式释放锁 成功 && 有等待的线程 -> 唤醒等待的线程
        if (tryRelease(arg)) {
            AbstractQueuedSynchronizer.Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    // java.util.concurrent.locks.ReentrantLock.Sync.tryRelease
    protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        // 如果c=0 -> 锁释放成功 && 独占线程置为null
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }

    

 

使用场景

  互斥锁

static ReentrantLock reentrantLock = new ReentrantLock(true);

    public static void main(String[] args) {
        Task task = new Task();
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        Thread t3 = new Thread(task);

        t1.start();
        t2.start();
        t3.start();
    }

    static class Task implements Runnable{
        @Override
        public void run() {
            try {
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName() + "获得lock");
            }
            finally {
                reentrantLock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放lock");
            }
        }
    }


结果:
Thread-0获得lock
Thread-0释放lock
Thread-1获得lock
Thread-1释放lock
Thread-2获得lock
Thread-2释放lock

  

lock、tryLock

区别

  Lock:

    如果锁当前未被其他线程持有,则立即获取锁;

    如果锁已经被其他线程持有,则当前线程会进入阻塞状态,直到锁变得可用为止。一旦线程获得了锁,它就会保持锁直到显式调用 unlock() 方法释放锁。

    如果锁不可用,线程会一直等待,直到锁可用。

    场景:

      用于确保线程能够在获取锁后执行关键操作,适合于需要长期等待锁的场景;    

  tryLock:

    试图获取锁,但它不会阻塞等待。如果锁当前未被其他线程持有,则立即获取锁;

    如果锁已经被其他线程持有,则当前线程不会等待,而是立即返回 false

    场景:

      用于尝试获取锁而不阻塞等待,适合于不需要长时间等待锁的场景,或者当锁不可用时可以采取其他行动的场景;    

lock.tryLock()

Acquires the lock only if it is not held by another thread at the time of invocation.    仅当调用时,锁未被其他线程持有时,才获取锁;
 
Acquires the lock if it is not held by another thread and returns immediately with the value {@code true}, setting the lock hold count to one.
Even when this lock has been set to use a fair ordering policy, a call to {@code tryLock()} <em>will</em> immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock.
This &quot;barging&quot; behavior can be useful in certain circumstances, even though it breaks fairness.
If you want to honor the fairness setting for this lock, then use {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } which is almost equivalent (it also detects interruption).
如果锁未被其他线程持有,则获取锁,并立即返回值{@code true},将锁持有计数设置为1。

即使此锁已设置为使用公平排序策略,对tryLock的调用也会立即获取可用的锁,无论其他线程当前是否正在等待该锁。
这种讨价还价行为在某些情况下可能是有用的,即使它破坏了公平。
如果你想遵守此锁的公平性设置,那么使用{@link#tryLock(long,TimeUnit)tryLock(0,TimeUnit.SECONDS)},这几乎是等效的(它也能检测到中断)。

 

If the current thread already holds this lock then the hold count is incremented by one and the method returns {@code true}.
If the lock is held by another thread then this method will return immediately with the value {@code false}.

如果当前线程已经持有此锁,则持有计数将增加1,该方法将返回{@code true}。
如果锁由另一个线程持有,则此方法将立即返回值{@code false}。

 

非公平锁

/**
     * ReentrantLock lock = new ReentrantLock();
     * lock.tryLock();
     *
     * java.util.concurrent.locks.ReentrantLock#tryLock()
     *      public boolean tryLock() {
     *         return sync.nonfairTryAcquire(1);
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire(int)
     *      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()) {                 // 如果 有线程持有锁 & 独占线程是自己  -> 重复获取锁 state+1
     *                 int nextc = c + acquires;
     *                 if (nextc < 0) // overflow
     *                     throw new Error("Maximum lock count exceeded");
     *                 setState(nextc);
     *                 return true;
     *             }
     *             return false;
     *         }
     */

 

公平锁 

/**
     * ReentrantLock lock = new ReentrantLock(true);
     * lock.tryLock();
     *
     * java.util.concurrent.locks.ReentrantLock#tryLock()                           // 和非公平锁逻辑一样,以独占式获取锁
     *      public boolean tryLock() {
     *         return sync.nonfairTryAcquire(1);
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire(int)
     *      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()) {                 // 如果 有线程持有锁 & 独占线程是自己  -> 重复获取锁 state+1
     *                 int nextc = c + acquires;
     *                 if (nextc < 0) // overflow
     *                     throw new Error("Maximum lock count exceeded");
     *                 setState(nextc);
     *                 return true;
     *             }
     *             return false;
     *         }
     */

  

  

lock.lock()

Acquires the lock.
Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.
If the current thread already holds the lock then the hold count is incremented by one and the method returns immediately.
If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired, at which time the lock hold count is set to one.

获得锁。
如果锁未被其他线程持有,则获取锁并立即返回,将锁持有计数设置为1。
如果当前线程已经持有锁,则持有计数将增加1,方法将立即返回。
如果锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到获取到锁为止,此时锁持有计数设置为1。

 

非公平锁

 /**
     * ReentrantLock lock = new ReentrantLock();
     * lock.lock()
     *
     * java.util.concurrent.locks.ReentrantLock#lock()
     *      public void lock() {
     *         sync.lock();
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#lock()
     *      abstract void lock();
     *
     * java.util.concurrent.locks.ReentrantLock.NonfairSync#lock()
     *      final void lock() {
     *             if (compareAndSetState(0, 1))                                            // 如果获取锁成功 -> 设置当前线程独占
     *                 setExclusiveOwnerThread(Thread.currentThread());
     *             else                                                                     // 否则 -> 独占式获取锁
     *                 acquire(1);
     *         }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire(int)
     *      public final void acquire(int arg) {
     *         if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))       // 如果获取锁失败 & 加入同步队列成功 -> 自我中断阻塞
     *             selfInterrupt();
     *     }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire(int)
     *      protected boolean tryAcquire(int arg) {
     *         throw new UnsupportedOperationException();
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire(int)
     *      protected final boolean tryAcquire(int acquires) {
     *             return nonfairTryAcquire(acquires);
     *         }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire(int)     // 和tryLock一样的逻辑
     *      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()) {                 // 如果 有线程持有锁 & 独占线程是自己  -> 重复获取锁 state+1
     *                 int nextc = c + acquires;
     *                 if (nextc < 0) // overflow
     *                     throw new Error("Maximum lock count exceeded");
     *                 setState(nextc);
     *                 return true;
     *             }
     *             return false;
     *         }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued(java.util.concurrent.locks.AbstractQueuedSynchronizer.Node, int)
     *      final boolean acquireQueued(final Node node, int arg) {
     *         boolean failed = true;
     *         try {
     *             boolean interrupted = false;
     *             for (;;) {
     *                 final Node p = node.predecessor();
     *                 if (p == head && tryAcquire(arg)) {
     *                     setHead(node);
     *                     p.next = null; // help GC
     *                     failed = false;
     *                     return interrupted;
     *                 }
     *                 if (shouldParkAfterFailedAcquire(p, node) &&
     *                     parkAndCheckInterrupt())
     *                     interrupted = true;
     *             }
     *         } finally {
     *             if (failed)
     *                 cancelAcquire(node);
     *         }
     *     }
     *
     */

  

  

公平锁

/**
     * ReentrantLock lock = new ReentrantLock(true);
     * lock.lock();
     *
     * java.util.concurrent.locks.ReentrantLock#lock()
     *      public void lock() {
     *         sync.lock();
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#lock()
     *      abstract void lock();
     *
     * java.util.concurrent.locks.ReentrantLock.FairSync#lock()
     *      final void lock() {
     *             acquire(1);
     *         }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire(int)               // 和非公平锁逻辑一样
     *      public final void acquire(int arg) {
     *         if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))       // 如果获取锁失败 & 加入同步队列成功 -> 自我中断阻塞
     *             selfInterrupt();
     *     }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire(int)
     *      protected boolean tryAcquire(int arg) {
     *         throw new UnsupportedOperationException();
     *     }
     *
     * java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire(int)
     *      protected final boolean tryAcquire(int acquires) {
     *             return nonfairTryAcquire(acquires);
     *         }
     *
     * java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire(int)     // 和tryLock一样的逻辑
     *      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()) {                 // 如果 有线程持有锁 & 独占线程是自己  -> 重复获取锁 state+1
     *                 int nextc = c + acquires;
     *                 if (nextc < 0) // overflow
     *                     throw new Error("Maximum lock count exceeded");
     *                 setState(nextc);
     *                 return true;
     *             }
     *             return false;
     *         }
     *
     * java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued(java.util.concurrent.locks.AbstractQueuedSynchronizer.Node, int)
     *      final boolean acquireQueued(final Node node, int arg) {
     *         boolean failed = true;
     *         try {
     *             boolean interrupted = false;
     *             for (;;) {
     *                 final Node p = node.predecessor();
     *                 if (p == head && tryAcquire(arg)) {
     *                     setHead(node);
     *                     p.next = null; // help GC
     *                     failed = false;
     *                     return interrupted;
     *                 }
     *                 if (shouldParkAfterFailedAcquire(p, node) &&
     *                     parkAndCheckInterrupt())
     *                     interrupted = true;
     *             }
     *         } finally {
     *             if (failed)
     *                 cancelAcquire(node);
     *         }
     *     }
     */

  

公平锁与非公平锁的区别 

/**
     * java.util.concurrent.locks.ReentrantLock.FairSync#lock()
     *      final void lock() {
     *             acquire(1);
     *         }
     *         
     * java.util.concurrent.locks.ReentrantLock.NonfairSync#lock()
     *      final void lock() {
     *             if (compareAndSetState(0, 1))                                    非公平锁 无视同步队列,直接去获取锁
     *                 setExclusiveOwnerThread(Thread.currentThread());
     *             else
     *                 acquire(1);
     *         }
     */

  

 

 

posted on 2023-10-23 17:03  anpeiyong  阅读(13)  评论(0编辑  收藏  举报

导航