Lock与ReentrantLock
Lock
提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显示的。
1 | //Lock接口 |
ReentrantLock
实现了Lock
接口,并提供了与synchronized
相同的互斥性和内存可见性。
1 | //使用ReentrantLock来保护对象状态 |
在synchronized和ReentrantLock之间进行选择
ReentrantLock
在加锁和内存上提供的语义与内置锁相同,此外它还提供了一些其他功能,包括定时的锁等待、可中断的锁等待、公平性,以及实现非块结构的加锁。
ReentrantLock
的危险性比同步机制要高,如果忘记在finally
块中调用unlock
,那么虽然代码表面上能正常运行,但实际上已经埋下隐患。
仅当内置锁不能满足需求时,才考虑使用ReentrantLock
。
在一些内置锁无法满足需求的情况下,
ReentrantLock
可以作为一种高级工具。当需要一些高级功能时才应该使用ReentrantLock
,这些功能包括:可定时的、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁。否则,还是应该优先使用synchronized
。
读-写锁
ReadWriteLock
中暴露了两个Lock
对象,其中一个用于读操作,而另一个用于写操作。要读取由ReadWriteLock
保护的数据,必须首先获得读取锁,当需要修改ReadWriteLock
保护的数据时,必须首先获得写入锁。
1 | //ReadWriteLock接口 |
在读-写锁实现的加锁策略中,允许多个读操作同时进行,但每次只允许一个写操作。
小结
与内置锁相比,显示的Lock
提供了一些扩展功能,在处理锁的不可用性方面有着更高的灵活性,并且对队列有着更好的控制。但ReentrantLock
不能完全替代synchronized
,只有在synchronized
无法满足需求时,才应该使用它。
读-写锁允许多个读线程并发地访问被保护的对象,当访问以读取操作为主的数据结构时,它能提高程序的可伸缩性。