内部所拥有比较好的性能,但是在灵活性方面有缺陷,并且如果申请锁失败就会陷入阻塞等待的过程中。
对于一些场景,我们可以使用显示锁lock
lock 的lock方法相当于进入同步块, unlock方法相当于退出同步块。支持跟内部锁同样的重入机制:
可以看出内部锁的代码还有清爽一点, 显示锁需要在finally中释放
先看下死锁的情况:
改为不会死锁的情况:
如上其实主要是利用了trylock当获取不到锁就返回false的特性。另外trylock还能设置超时时间,指定时间得不到锁才返回false.
当代码遇到锁标记有很多种选择,获得锁,如果锁不再了等待锁,重入进该锁, 响应中断。
通常的锁在需要等待的时候并不会响应中断。
如下:
使用lock()的返回结果:
使用lockinterruptibly()的返回结果:
可见lockinterruptibly与普通锁的区别在于可以在锁等待的时候响应中断
在jdk6之前性能上lock要好很多,但是jdk6之后改进了内部锁的算法,现在差不多
reentrantlock锁的构造器中可以选择是否公平,公平的意思就是开始执行的顺序将会按照锁等待的顺序。这样会造成性能下降,只有在对顺序敏感的时候才需要。
性能上jdk1.6,reentrantlock略好。
reentrantlock可以支持复杂的语义。
reentrantlock需要显示关闭
synchronized语法上更简单易用
综上,其实应该更多的使用synchoronized,只有在有必要的时候才使用reentrantlock
普通的锁限制了并发性,对于数据无害的读-读操作也会出现锁竞争。这个时候可以使用读写锁
读写锁的一些特性:
- 基本功能就是有写入的时候要等写完完成才能再执行写入,如果没有写入的时候读是可以并发的
- 可降级不可以升级,就是读解锁前如果获取写锁会死锁,但是写锁中是可以获取读锁的
- 各锁单独可重入
可以验证写锁互斥,读写并发。