synchronized 和 ReentrantLock 的区别

120 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

synchronized 和 ReentrantLock 的区别

synchronized的特点

synchronized 修饰的方法或者代码块在同一时刻,只能有一个线程在执行对应的代码逻辑。synchronized 可以使用到方法声明上,也可以使用在代码块上,当运行到对应被synchronized修饰的代码块时,线程会先检查是否有别的线程正在执行同步代码块,如果没有的话,会直接运行,如果有的话,线程会阻塞等待,等到其他线程执行完成后,再重新进行检查,判断是否能够执行相应的代码逻辑。

synchronized拥有可重入性,一个线程拿到对象对应锁的持有权后,可以再次请求对象内的其他synchronized方法的,这代表在执行synchronized方法时,调用当前对象的其他synchronized方法也是可以得到锁执行逻辑的。相反的,如果不具备可重入性,那么当线程获取对象锁之后,再执行对象的其他synchronized方法时,由于自身已经持有了对象锁,此时就会造成死锁的现象。

synchronized对任意对象加锁时,只需使用关键字synchronized修饰即可,锁的释放JAVA会自动执行,即使出现异常,JAVA也会自动 释放锁。

ReentrantLock的特点

ReentrantLock通常称作可重入锁,顾名思义,和synchronized一样,也是具有可重入性的。

ReentrantLock 对对象加锁时,需要显示的调用lock()方法,释放锁时,也需要显示的调用unlock方法,并且ReentrantLock可以自定义为公平锁或者是非公平锁。

ReentrantLock在出现异常时,并不会有自动释放锁的机制,此时会产生一直持有锁对象无法释放的情况,所以在实际的使用中,最好是结合try-catch一起使用。

总结

synchronized 相对于 ReentrantLock 来说,使用相对简单,但是synchronized 内部有锁升级的机制,所以在高并发情况下,synchronized的锁升级(最后升级为重量级锁),会导致效率变低。

synchronized可以自动释放锁,ReentrantLock必须手动释放锁。

ReentrantLock可以定义公平或者非公平锁,synchronized是非公平锁。