ReentrantLock 实现原理

使用 synchronized 来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现。

而 ReentrantLock 就是一个普通的类,它是基于 AQS(AbstractQueuedSynchronizer)来实现的。

是一个重入锁:一个线程获得了锁之后仍然可以反复的加锁,不会出现自己阻塞自己的情况。

锁类型

ReentrantLock 分为公平锁和非公平锁,可以通过构造方法来指定具体类型:

1    //默认非公平锁(默认一般都是非公平锁)
2     public ReentrantLock() {
3         sync = new NonfairSync();
4     }
5     
6     //公平锁
7     public ReentrantLock(boolean fair) {
8         sync = fair ? new FairSync() : new NonfairSync();
9     }

获取锁

 1  private ReentrantLock lock = new ReentrantLock();
 2     public void run() {
 3         lock.lock();
 4         try {
 5             //do bussiness
 6         } catch (InterruptedException e) {
 7             e.printStackTrace();
 8         } finally {
 9             lock.unlock();
10         }
11     }

释放锁

公平锁和非公平锁的释放流程都是一样的:

 1 public void unlock() {
 2         sync.release(1);
 3     }
 4     
 5     public final boolean release(int arg) {
 6         if (tryRelease(arg)) {
 7             Node h = head;
 8             if (h != null && h.waitStatus != 0)
 9                    //唤醒被挂起的线程
10                 unparkSuccessor(h);
11             return true;
12         }
13         return false;
14     }
15     
16     //尝试释放锁
17     protected final boolean tryRelease(int releases) {
18         int c = getState() - releases;
19         if (Thread.currentThread() != getExclusiveOwnerThread())
20             throw new IllegalMonitorStateException();
21         boolean free = false;
22         if (c == 0) {
23             free = true;
24             setExclusiveOwnerThread(null);
25         }
26         setState(c);
27         return free;
28     }    

首先会判断当前线程是否为获得锁的线程,由于是重入锁所以需要将 state 减到 0 才认为完全释放锁。

释放之后需要调用 unparkSuccessor(h) 来唤醒被挂起的线程。

posted @ 2020-04-16 16:26  seedss  阅读(275)  评论(0编辑  收藏  举报