前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >谈谈 synchronized 和 ReentrantLock 的区别

谈谈 synchronized 和 ReentrantLock 的区别

作者头像
happyJared
发布2019-07-08 18:03:19
2.3K0
发布2019-07-08 18:03:19
举报
文章被收录于专栏:happyJaredhappyJared

① 两者都是可重入锁

“可重入锁”概念是:自己可以再次获取自己的内部锁。比如,一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁时,还可以再获取的;如果不可锁重入的话,就会造成死锁;同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时,才能最终释放锁。

② synchronized 依赖于 JVM,而 ReentrantLock 依赖于 API

synchronized 是依赖于 JVM 实现的,Java 虚拟机团队在 JDK1.6 为 synchronized 关键字进行了很多的优化,但这些优化都是在虚拟机层面实现的,并没有直接暴露给我们。ReentrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成),可以通过查看它的源代码,来看它是如何实现的。

③ ReentrantLock 比 synchronized 增加了一些高级功能

相比 synchronized,ReentrantLock 增加了一些高级功能。主要有三点:① 等待可中断;② 可实现公平锁;③ 可实现选择性通知(锁可以绑定多个条件):

  • ReentrantLock 提供了一种能够中断等待锁线程的机制,通过 lock.lockInterruptibly() 来实现这个机制,也就是说正在等待的线程可以选择放弃等待,改为处理其他事情;
  • ReentrantLock 可以指定是公平锁还是非公平,而 synchronized 只能是非公平锁。所谓的公平锁,就是先等待的线程最先获得锁;ReentrantLock 默认是非公平的,可以通过 ReentrantLock 类的 ReentrantLock(boolean fair) 构造方法来制定是否是公平的;
  • synchronized 关键字结合 wait()notify()/notifyAll() 方法使用,可以实现等待/通知机制,ReentrantLock 类则需要借助于 Condition 接口与 newCondition() 方法。Condition 是 JDK1.5 之后才有的,它具有很好的灵活性,比如可以实现多路通知功能,也就是在一个 Lock 对象中可以创建多个 Condition 实例(即对象监视器),线程对象可以注册在指定的 Condition 中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。 在使用 notify()/notifyAll() 方法进行通知时,被通知的线程是由 JVM 选择的。而 synchronized 关键字就相当于整个 Lock 对象中只有一个 Condition 实例,所有的线程都注册在它一个身上。如果执行 notifyAll() 方法的话,就会通知所有处于等待状态的线程,这样会造成很大的效率问题,而 Condition 实例的 signalAll() 方法只会唤醒注册在该 Condition 实例中的所有等待线程。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档