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)
来唤醒被挂起的线程。