java多线程之ReentrantLock非公平锁源码解析

前言

上一篇咱们分析了ReentrantLock公平锁的获取和释放的源码,本篇再看非公平锁的源码就轻松多了,上一篇没看的建议先去看公平锁的源码分析。

1、获取非公平锁

下面是非公平锁获取锁的源码,是在ReentrantLock.java的NonfairSync类中。

final void lock() {
	//通过CAS判断"锁"是不是空闲状态
     if (compareAndSetState(0, 1))
     	//设置“当前线程”为“锁”的持有者
         setExclusiveOwnerThread(Thread.currentThread());
     else
         acquire(1);
 }

acquire()在AbstractQueuedSynchronizer(AQS)抽象类中定义的,它的源码如下:

 //注意,acquire方法中,tryAcquire方法是由公平锁类和非公平锁类自己实现的
 //addWaiter、acquireQueued、selfInterrupt方法是由AQS自己实现的
 public final void acquire(int arg) {
     if (!tryAcquire(arg) &&
         acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
         selfInterrupt();
}

1.1、tryAcquire方法

非公平锁的tryAcquire()在ReentrantLock.java的NonfairSync类中实现,源码如下:

protected final boolean tryAcquire(int acquires) {
     return nonfairTryAcquire(acquires);
}

nonfairTryAcquire()在ReentrantLock.java的Sync类中实现,源码如下:

final boolean nonfairTryAcquire(int acquires) {
      final Thread current = Thread.currentThread();
      int c = getState();
      if (c == 0) {
      	  //细心的同学可能已经发现了,这里比公平锁的少了一行代码
      	  //少了的那行代码是:!hasQueuedPredecessors(),判断自己是不是等待队列的第一个
          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;
 }

2、释放非公平锁

释放非公平锁和释放公平锁是一样的,这里不重复说明,忘记了的,可以再回去看看公平锁的释放方法。

3、公平锁和非公平锁的区别

  1. 公平锁和非公平锁的区别,是在获取锁的机制上。
  2. 公平锁只有当前线程在队列的头部且锁是空闲的才能获取锁。
  3. 非公平锁只要锁是空闲的,当前线程就可以直接获取锁。
  4. 非公平锁在尝试获取锁失败后,才会像公平锁一样,在队列排队获取锁。

结束语

本篇结束了非公平锁的源码分析,并且总结了“独占锁”ReentrantLock公平锁和非公平锁的区别,下一篇将分析共享锁ReentrantReadWriteLock。

原创文章 55 获赞 76 访问量 17万+

猜你喜欢

转载自blog.csdn.net/cool_summer_moon/article/details/106018800