Synchronized和Reentrantlock的区别
1. Reentrantlock的使用
1. 初始化选择公平锁还是非公平锁
Reentrantlock lock = new Reentrantlock(true);
2. 可用于代码块
lock.lock();
try{
}finally{
3. 释放锁
lock.unlock();
}
return ResponseUtil.success();
2. Reentrantlock的原理
Reentrantlock有两种使用模式,一种是公平锁,一种是非公平锁,通过在创建实例的时候传参设置。
1. 设置公平模式
Reentrantlock lock = new Reentrantlock(true);
2. 设置非公平模式
Reentrantlock lock = new Reentrantlock();
// 公平模式下Reentrantlock的构造函数源码
public ReentrantLock() {
this.sync = new ReentrantLock.NonfairSync();
}
// 非公平模式下Reentrantlock的构造函数源码
public ReentrantLock(boolean fair) {
this.sync = (ReentrantLock.Sync)(fair ? new ReentrantLock.FairSync() : new ReentrantLock.NonfairSync());
}
其中涉及到几个类:FairSync、NonfairSync,这两个类是Reentrantlock中的内部类,Reentrantlock的结构图如下。从结构图可以看出,Reentrantlock的主要实现都交给AQS(AbstractQueuedSynchronizer类)去实现。
2.1 Reentrantlock的lock方法在AQS中的实现
1. lock --> acquire
public void lock() {
this.sync.acquire(1);
}
2. acquire --> tryAcquire
public final void acquire(int arg) {
if (!this.tryAcquire(arg) && this.acquireQueued(this.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
}
3. tryAcquire在FairSync中的实现
4. tryAcquire在NonfairSync中的实现
2.2 公平模式和非公平模式下上锁流程的简单理解
公平模式
非公平模式
AQS使用state同步状态,0表示未上锁,1表示上锁。如果当前线程无法抢占到锁资源,AQS会将其放入到双向队列中阻塞。
3. Synchronized和Reentrantlock的区别
1. 核心区别:
Synchronized适合于并发竞争低的情况,原因是Synchronized当遇到竞争激励的并发情况时,锁会升级成重量级锁,而一旦升级完成后,锁不会完成降级。
Reentrantlock适合于动态高并发的情况,原因是Reentrantlock通过在高并发下线程的挂起,来减少竞争,提高并发能力。
2. Synchronized是关键字,是jvm层面实现的;Reentrantlock是java api实现的。
3. Synchronized是隐式锁,会自动释放;Reentrantlock是显式锁,需要手动调用unlock释放锁资源。
4. Synchronized不能响应中断;Reentrantlock可以。