Java 并发编程学习(八):Java 中的锁
内置锁
Java中,内置锁指的是synchronize关键字代表的锁机制。在前面的文章中曾介绍了synchronize的用法。synchronize的特点:
- 使用简单,不需要显式地加锁和释放锁
- 因获取锁而被阻塞的线程,不能响应中断、不支持超时机制
- 不支持多个condition
- 非公平的锁,不保证最先等待锁的线程在锁释放之后首先获得锁
- 可重入
类库中的Lock
- 需要显式的执行lock、unlock操作
- 支持响应中断、非阻塞的获取锁、超时机制
- 支持公平锁
- 可重入
- 支持多个condition
synchronize和Lock如何选择
虽然Lock类库提供的锁机制拥有更加强大的能力,但是在使用的时候,出错的风险也更多。就性能方面来说,Java 6 之后,synchronize经过优化,已经基本能够达到Lock的性能。因此,在任何场景中,除非synchronize不满足需求,否则没有必要使用Lock。
锁的相关话题
死锁:锁是互斥的、持有的锁是不可抢占的,只能由占有者主动释放、多个线程出现循环等待锁、占有锁且等待别的锁。
- 获取到一个锁之后,接下来再调用别的外部方法时,需要考虑这个外部方法中是否会持有别的锁。如果在不知情的情况下线程又取得了另一个锁,那么有出现死锁的风险。
- 在获取一个锁时,需要考虑这个锁在别处有没有线程也可以获取到,如果有,需要分析两处的取锁逻辑有没有产生依赖。
活锁:当多个相互协作的线程因彼此响应而修改自身状态,从而导致任何一个线程都不能继续往下执行,这种状态称为出现活锁。
解决活锁:避免活锁最简单的方法是在重试机制中引入随机性。