锁的概述(二)--公平锁与非公平锁

1 简介

根据线程获取锁的抢占机制,锁可以分为公平锁和非公平锁。

  • 公平锁:获取锁的顺序按照线程请求锁的时间顺序决定,ji简单来说,早申请早获取到锁,晚申请晚获取到锁。
  • 非公平锁:获取锁的顺序不一定按照请求锁的时间来决定,早申请不一定先得到锁。

2 实现

ReentrantLock 提供了公平锁与非公平锁的实现:

  • 公平锁:ReentrantLock pairLock = new ReentrantLock(true);
  • 非公平锁:ReentrantLock pairLock = new ReentrantLock(false);
    没有公平性需求尽量使用非公平锁,公平锁会带来额外的性能开销。

3 原理

ReentrantLock 的公平锁和非公平锁最终都委托抽象同步队列 AQSacquire()来获取

//AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
       //抽象方法,实现类去实现该方法
       if (!tryAcquire(arg) &&
           //acquireQueued():多次尝试获取锁或者阻塞
           //addWaiter():将线程结点加入到等待队列
           acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
           //线程中断,调用`Thread.currentThread().interrupt()` 中断线程
           selfInterrupt();
}

3.1 公平锁

//锁
final void lock() {
    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;
}

public final boolean hasQueuedPredecessors() {
        Node t = tail; 
        Node h = head;
        Node s;
        //1.如果该线程由前驱结点返回 true,
        //2.否则,如果当前 AQS 队列为空或者当前线程结点是第一个结点返回 false
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }    

3.2 非公平锁

//锁
final void lock() {
    //lock 时候,随机抢占,直接进行加锁操作,而公平锁是直接调用 acquire(1)
    if (compareAndSetState(0, 1))
         setExclusiveOwnerThread(Thread.currentThread());
    else
       acquire(1);
}


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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值