synchronized和ReentrantLock的区别

重入锁可以说是synchronized的替代品甚至可以说是增强版,重入锁可以完全替代synchronized关键字。看到网上有很多重入锁的性能远远好于synchronized的说法,事实上,在JDK5.0以前的确这样,但从JDK6.0开始,JDK在synchronized做了大量的优化,使得两者的性能差距并不大。
1.重入锁的灵活性更好
与synchronized相比,重入锁有着现实的操作过程,开发人员必须手动指定何时加锁以及何时释放锁,也正因为这样, 重入锁对逻辑控制的灵活性要好于synchronized。但值得注意的是,在退出临界区时,必须记得释放锁,否则,其他线程就没有机会再访问临界区了(通常我们会将释放锁放在finally块中)。
2.重入锁可以提供中断处理的能力
除了使用上的灵活性之外,重入锁还提供了一些高级功能。比如,重入锁可以提供中断处理的能力。
对于synchronized来说,如果一个线程在等待锁,那么结果只有两种情况,要么它获得这把锁继续执行,要么它就继续保持等待。而使用重入锁,则提供另外一种可能,那就是线程可以被中断。也就是在等待锁的过程中,程序可以根据需要取消对锁的请求。有些时候这么做是非常必要的,比如你和朋友约好一起去打球,如果你等了半个小时,朋友还没到,突然接到一个电话,说突发情况,不能如约了,那么你一定就扫兴的打道回府了。
中断正式提供了一套类似的机制。如果一个此案城正在等待锁,那么它依然可以收到一个通知,被告知无须再等待,可以停止工作了,这种情况对于处理死锁是有一定帮助的。
重入锁提供lockInterruptibly()方法实现可中断的锁,外界可以通过调用interrupt()来中断线程
3.锁申请等待限时
处理等待外部通知之外,要避免死锁还有另外一种方法,就是限时等待。依然以约朋友打球为例,如果朋友迟迟不来,又无法联系到他,那么在等待1-2个小时后,我想大部分人都会扫兴离去。对线程来说也是这样,通常我们无法判断为什么一个线程迟迟拿不到锁,也许是死锁了,也许是因为产生了饥饿,单如果给定一个等待时间,让线程自动放弃,那么对系统来说是有意义的。我们可以使用tryLock()方法进行一次限时的等待。tryLock()方法有两个参数,一个表示等待时长,一个表示计时单位,如果超过这个计时还没获得锁,就会返回false,如果获得锁返回true。tryLock()方法也可以不带参数直接运行,这种情况下当前线程会尝试获取锁,如果锁未被占用,则获取锁成功,返回true,如果锁被其他线程占用,则当前线程不会进行等待,立即返回false。这种模式不会引起线程等待,因此也不会产生死锁。
4.公平锁
在大多数情况下,锁的申请都是非公平的。也就是说,当线程1首先请求获取锁,接着线程2也请求获取锁,那么当锁可用时,不一定哪个线程会获取锁。因此不能保证其公平性。与之对应的则为公平锁,它会按照时间的先后顺序保证先到先得。公平锁的特点是不会产生饥饿,而synchronized是不能做到公平锁的。重入锁提供了一个构造函数public ReentrantLock(boolean fair)来控制是否是公平锁。当fair为true时表示为公平锁。不过因为公平锁需要维护一个有序队列,因此性能比较低下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值