Java5.0以后除了内置锁synchronized外在concurrent包还提供了显式锁接口Lock。
何为显式?
就是显式地加锁和解锁,需要自己写代码去加锁和解锁。Synchronized是隐式加锁解锁,也就是无需自己写加锁解锁代码,进了synchronized代码块就隐式加锁,出了代码块就隐式解锁。
下图为使用显式锁保证计数结果正确的demo:
在lock和unlock之间的代码是被同步的,并且和synchronized一样具有内存可见性。
Lock除了普通的lock和unlock,相比synchronized,多了一些新特性:
1.返回是否成功获取锁的lock:Boolean tryLock()
尝试获取锁,获取成功返回true,获取失败返回false。
2.定时获取锁的lock:boolean tryLock(long timeout,
[TimeUnit](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html "enum in java.util.concurrent") unit)
throws [InterruptedException](https://docs.oracle.com/javase/7/docs/api/java/lang/InterruptedException.html "class in java.lang")
在指定时间内获取锁成功返回true,超时返回false。
显式锁的一些扩展特性:
1.一些特定的显式锁可以实现分段锁,比如ReentrantReadWriteLock,管理读锁和写锁,读写锁相对于synchronized这种互斥锁来说可以支持更高的并发,读锁不互斥,写锁互斥,增加吞吐量。
公平性,ReentrantLock构造函数的参数可以设置锁是公平还是非公平的,非公平性的锁不保证执行顺序,哪个线程先到就执行哪个线程。非公平锁性能>公平锁性能
锁降级,写锁降为读锁。
可重入。
Synchronized和显式锁如何选择?
Synchronized能满足需求时尽量用synchronized,减少代码复杂度和忘记解锁的风险。
当synchronized满足不了需求,需要用到一些新特性比如分段锁,公平性调整等特性时,可以考虑用显式锁。