目录
一.用法不同
synchronized是Java的关键字,它可以用来修饰普通方法、静态方法和代码块,而 ReentrantLock 是创建的实例对象,只能用在代码块上。
synchronized的使用方法
1.修饰普通方法
public class Demo {
//修饰普通方法
public synchronized void add(){
//方法逻辑
}
}
2.修饰静态方法
public class Demo {
//修饰静态方法
public static synchronized void add(){
//静态方法逻辑
}
}
3.修饰代码块
public class Demo {
public void add(){
//修饰代码块
synchronized (this){
//代码块内的逻辑
}
}
}
ReentrantLock的使用方法
ReentrantLock只能用在代码块上,首先需要创建ReentrantLock对象,调用lock方法开启锁,调用unlock方法释放锁
public class Demo {
public void add(){
//创建ReentrantLock锁对象
ReentrantLock lock=new ReentrantLock();
//开启ReentrantLock锁
lock.lock();
try {
//代码块逻辑
//......
}finally {
//释放ReentrantLock锁
lock.unlock();
}
}
}
二.获取锁和释放锁方式不同
synchronized为Java的关键字,ReentrantLock需要创建对象调用lock方法,synchronized自动释放锁,而ReentrantLock则需要调用unlock来释放锁。
三.锁类型不同
synchronized为非公平锁,而ReentrantLock可以根据传入的参数设置为公平锁或非公平锁。
参数为 true表示公平策略,否则,采用非公平策略。
非公平锁:每一次都尝试获取锁,不会按照公平等待的原则进行等待,不会让等待时间最久的线程获得锁。
公平锁:当资源空闲时,它总是会先判断 sync队列是否有等待时间更长的线程,如果存在,则将当前线程加入到等待队列的尾部,实现了公平获取原则。
public class Demo {
public void add(){
//创建ReentrantLock锁对象
//默认为非公平锁
//传入true为公平锁
ReentrantLock lock=new ReentrantLock(true);
}
}
四.是否可中断
synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成; ReentrantLock则可以中断,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中,调用interrupt方法进行中断。
public class Demo {
public void add() throws InterruptedException {
ReentrantLock lock=new ReentrantLock(true);
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
// ...
} finally {
lock.unlock();
}
}
}
}
五.低层实现不同
synchronized 是 JVM 层面通过监视器(Monitor)实现的,而 ReentrantLock 是通过 AQS(AbstractQueuedSynchronizer)程序级别的 API 实现。 synchronized 通过监视器实现, 其中 monitorenter 表示进入监视器,相当于加锁操作,而 monitorexit 表示退出监视器,相当于释放锁的操作。 ReentrantLock 是通过 AQS 实现,
六.总结
synchronized 和 ReentrantLock 都是 Java 中提供的可重入锁,二者的主要区别有以几个:
- 用法不同:synchronized 可以用来修饰普通方法、静态方法和代码块,而 ReentrantLock 只能用于代码块。
- 获取锁和释放锁的机制不同:synchronized 是自动加锁和释放锁的,而 ReentrantLock 需要手动加锁和释放锁。
- 锁类型不同:synchronized 是非公平锁,而 ReentrantLock 默认为非公平锁,也可以手动指定为公平锁。
- 中断机制不同:synchronized是不可中断,ReentrantLock则,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中中断。
- 底层实现不同:synchronized 是 JVM 层面通过监视器实现的,而 ReentrantLock 是基于 AQS 实现的。