zoukankan      html  css  js  c++  java
  • 深入分析ReentrantLock公平锁和非公平锁的区别

    在ReentrantLock中包含了公平锁和非公平锁两种锁,通过查看源码可以看到这两种锁都是继承自Sync,而Sync又继承自AbstractQueuedSynchronizer,而AbstractQueuedSynchronizer又继承自AbstractOwnableSynchronizer,下面是类的继承关系图:


    其中AbstractOwnableSynchronizer是提供了设置占用当前锁的线程信息的方法,主要的锁的实现还是在AbstractQueuedSynchronizer中实现的,在AbstractQueuedSynchronizer中通过CLH队列实现了多线程锁的排队使用,但是该队列的实现并不能保证锁的公平竞争,但是在某些业务场景中会需要保证先到的线程先得到锁,所以就有了公平锁和非公平锁的诞生。

    通过分析ReentrantLock中的公平锁和非公平锁的实现,其中tryAcquire是公平锁和非公平锁实现的区别,下面的两种类型的锁的tryAcquire的实现,从中我们可以看出在公平锁中,每一次的tryAcquire都会检查CLH队列中是否仍有前驱的元素,如果仍然有那么继续等待,通过这种方式来保证先来先服务的原则;而非公平锁,首先是检查并设置锁的状态,这种方式会出现即使队列中有等待的线程,但是新的线程仍然会与排队线程中的对头线程竞争(但是排队的线程是先来先服务的),所以新的线程可能会抢占已经在排队的线程的锁,这样就无法保证先来先服务,但是已经等待的线程们是仍然保证先来先服务的,所以总结一下公平锁和非公平锁的区别:

    1、公平锁能保证:老的线程排队使用锁,新线程仍然排队使用锁。
    2、非公平锁保证:老的线程排队使用锁;但是无法保证新线程抢占已经在排队的线程的锁。

    公平锁的tryAcquire

    /**
    * Fair version of tryAcquire. Don't grant access unless
    * recursive call or no waiters or is first.
    */
    protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
    // !hasQueuedPredecessors()保证了不论是新的线程还是已经排队的线程都顺序使用锁
    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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    非公平锁的

    /**
    * Performs non-fair tryLock. tryAcquire is implemented in
    * subclasses, but both need nonfair try for trylock 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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ReentrantLock和LockSupport

    http://blog.47777205.com/
    http://blog.47777205.com/view/4
    ---------------------
    作者:m47838704
    来源:CSDN
    原文:https://blog.csdn.net/m47838704/article/details/80013056
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    JQuery-文档处理&选择器
    JQuery-事件(部分)
    JS中构造函数与函数
    JS中的String.Math.Date
    JS中的_proto_(2)
    JS中的_proto_
    JS中的constructor
    mysql 安装问题
    【转】SpringMVC中DispatcherServlet配置中url-pattern 配置/*和/的区别
    【转】MySql中的函数
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/10224119.html
Copyright © 2011-2022 走看看