原文网址:Java多线程--ReentrantLock的用法和原理_IT利刃出鞘的博客-CSDN博客
简介
说明
本文介绍Java的JUC中的ReentrantLock(可重入独占式锁)。包括:用法、原理。
概述
ReentrantLock主要利用AQS队列来实现。它支持公平锁和非公平锁。
AQS队列使用了CAS,所以ReentrantLock有CAS的优缺点。优点:性能高。缺点:CPU占用高。
ReentrantLock的流程
- state初始化为0,表示未锁定状态
- A线程lock()时,会调用tryAcquire()获取锁并将state+1
- 其他线程tryAcquire获取锁会失败,直到A线程unlock() 到state=0,其他线程才有机会获取该锁。
- A释放锁之前,自己可以重复获取此锁(state累加),这就是可重入的概念。
注意:获取多少次锁就要释放多少次锁,保证state能回到0。
示例
private Lock lock = new ReentrantLock();
public void test(){
lock.lock();
try{
doSomeThing();
}catch (Exception e){
// ignored
}finally {
lock.unlock();
}
}
公平与非公平
ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
- 非公平锁
- 如果同时还有另一个线程进来尝试获取,那么有可能会让这个线程抢先获取;
- 公平锁
- 如果同时还有另一个线程进来尝试获取,当它发现自己不是在队首的话,就会排到队尾,由队首的线程获取到锁。
ReentrantLock提供了两个构造器,分别是
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
NonfairSync的lock()方法
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
首先用一个CAS操作,判断state是否是0(表示当前锁未被占用),如果是0则把它置为1,并且设置当前线程为该锁的独占线程,表示获取锁成功。当多个线程同时尝试占用同一个锁时,CAS操作只能保证一个线程操作成功,剩下的只能去排队啦。
上边是文章的部分内容,为便于维护,全文已迁移到此网址:Java-ReentrantLock的用法和原理 - 自学精灵