Lock与ReentrantLock

Lock提供了一种无条件的, 可轮询的, 定时的以及可中断的锁获取操作, 所有加锁与解锁的方法都是显式的
image.png

ReentrantLock实现了Lock接口, 并提供了与synchronized相同的互斥性以及内存可见性
image.png

轮询锁与定时锁

轮询锁与定时锁模式是通过tryLock()方法实现的, 与无条件的锁获取模式相比, 它具有更完善的错误恢复机制

如下轮询锁示例:

  • 通过tryLock可以避免顺序死锁, 若不能获取所有的锁时, 则会先释放所有的锁, 再重新尝试获取
  • 休眠时间保护固定部分和随机部分, 可以降低活锁的可能性

image.png

如下定时锁示例:

  • 实现了带有时间限制的操作, 若超时则返回平缓的失败

image.png

可中断的锁获取操作

  • lockInterruptibly能够在获得锁的同时保持对中断的响应
  • 定时的tryLock也能响应中断

image.png

性能考虑因素

  • ReentrantLock可以构造公平锁, 当持有锁的时间相对较长, 或者请求锁的平均时间间隔较长, 那么应该使用公平锁

synchronized与ReentrantLock的选择

在一些内置锁无法满足需求的情况下, ReentrantLock可以作为一种高级工具, 当需要一些高级功能时才应该使用ReentrantLock, 这些功能包括: 可定时的, 可轮询的, 可中断的锁获取操作, 公平队列, 以及非块结构的锁, 否则, 还是应该优先使用synchronized

读写锁

  • 允许多个读操作同时进行, 但每次只允许一个写操作
  • 当访问以读取操作为主的数据结构时, 它能提高程序的可伸缩性

image.png

使用读写锁包装Map示例, 当需要例如对LinkedHashMap做包装时, 可以参考
image.png