这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
WangScaler: 一个用心创作的作者。
声明:才疏学浅,如有错误,恳请指正。
两者对比
- synchronized是属于jvm层面的的关键字,底层通过monitorenter、monitorexit指令实现的;而lock是属于一个类。
- synchronized在代码执行异常时或正常执行完毕后,jvm会自动释放锁;而lock不行使用lock必须加上异常处理,而且必须在finally块中写上unlock()释放锁。
- synchronized不可中断,只能等待程序执行完毕或者异常退出;而lock可通过interrupt来中断,可参考示例。
- synchronized不能精确唤醒指定的线程;而lock可以通过Condition精确唤醒。可参考示例。
- synchronized无法判断锁的状态,从而无法知道是否获取锁;而lock可以判断锁的状态,可参考示例。
中断响应
lock可以通过interrupt中断,而isInterrupted可以判断线程是否被中断。
1 | java复制代码package com.wangscaler.lock; |
首先启动线程,如果num小于10则不中断线程,此时循环执行,直到num自增到10,则执行中断Thread.currentThread().interrupt();
,此时循环条件变为false,线程结束。而synchronized一旦执行不能中断,要么执行完毕,要么程序异常。
lock精确唤醒示例
lock可以通过Condition精确唤醒。
比如我们有三个线程A、B、C,我们需要保证他们的执行顺序是A-B-C那么我们可以这样写当A线程执行完通过signal();方法来唤醒B,同理一次类推循环唤醒。
1 | java复制代码package com.wangscaler.lock; |
当然这些线程之间就像存在依赖关系一样,只有A能唤醒B,B唤醒C,C唤醒A。就像上述的案例三个线程都是执行4次,可以保证程序的正确执行,但是当B线程改为3次,程序就无法终止,因为C线程一直处于await状态,等待B线程的唤醒,然而B线程已经结束了。不过lock能精确的控制线程的执行顺序,而synchronized则做不到这点,synchronized只能随机唤醒线程。
获取锁的状态
而lock可以通过tryLock判断锁的状态。
1 | java复制代码package com.wangscaler.lock; |
tryLtrock方法尝试去获取锁,如果获取成功则返回布尔值true,如果获取失败则返回false。所以可以根据tryLtrock()来判断线程是否获的锁。
总结:
在资源竞争不是很激烈的情况下,可以选择synchronized,反之选择lock。synchronized是由jvm管理的,对程序员的要求较低,而lock则相反,如果操作不当,反而会带来严重的后果。
synchronized已经加入了线程自旋和适应性自旋以及锁消除、锁粗化、偏向锁,慢慢的从重量级锁转换成轻量级锁,优势也越来越明显。总之如何选择,大家根据实际情况进行选择吧。
来都来了,点个赞再走呗!
关注WangScaler,祝你升职、加薪、不提桶!
本文转载自: 掘金