乐观锁、悲观锁、重入锁、公平锁、非公平锁以及锁的粒度是并发编程中常用的概念和技术,它们用于控制多个线程对共享资源的访问。下面对这些概念逐一进行详细解释:
1. 乐观锁(Optimistic Locking):
乐观锁是一种乐观的并发控制策略,它假设多个线程之间很少发生竞争,因此在访问共享资源时不会立即阻塞其他线程。当一个线程要修改共享资源时,它首先获取该资源的一个版本标识(通常是一个版本号或时间戳),然后进行修改操作。在提交修改时,线程会检查该资源的版本标识是否与之前获取的一致,如果一致则说明没有发生竞争,修改成功;如果不一致则说明有其他线程修改了该资源,需要进行冲突处理。
2. 悲观锁(Pessimistic Locking):
悲观锁是一种悲观的并发控制策略,它假设多个线程之间会频繁发生竞争,因此在访问共享资源时立即将其他线程阻塞,以防止数据不一致。悲观锁常用的实现是通过 synchronized 关键字或 ReentrantLock 来实现的,当一个线程获得悲观锁后,其他线程会被阻塞,直到锁被释放。
3. 重入锁(Reentrant Lock):
重入锁是一种特殊的悲观锁,它允许同一个线程多次获取同一个锁,而不会被阻塞。重入锁实现了线程的可重入性,即同一个线程可以多次获取锁,而不会死锁。Java 中的 ReentrantLock 就是重入锁的一种实现。
4. 公平锁(Fair Lock):
公平锁是一种锁的获取策略,它保证多个线程获取锁的顺序是按照请求锁的先后顺序来的。当一个线程请求锁时,如果锁是公平的,它会被放入等待队列中,直到前面的线程都释放了锁,才会被唤醒获取锁。公平锁通常采用先进先出(FIFO)的方式来维护等待队列。
5. 非公平锁(Non-Fair Lock):
非公平锁是一种锁的获取策略,它不保证多个线程获取锁的顺序,允许后面的线程插队,直接尝试获取锁。当一个线程请求锁时,如果锁是非公平的,它会先尝试直接获取锁,只有当直接获取失败后才会放入等待队列。
6. 锁的粒度:
锁的粒度指的是锁的范围和粒度大小。锁的粒度可以是细粒度锁(Fine-Grained Locking)和粗粒度锁(Coarse-Grained Locking)两种。
- 细粒度锁:锁的范围比较小,只锁定共享资源的一小部分,多个线程可以并发访问共享资源的不同部分,从而提高并发性能。
- 粗粒度锁:锁的范围比较大,锁定整个共享资源,多个线程只能串行访问共享资源,因此可能导致性能瓶颈。
锁的粒度选择需要根据实际情况来决定,以满足线程安全和高效率的要求。细粒度锁可以提高并发性能,但也可能引入更多的锁竞争;粗粒度锁可以简化同步问题,但可能导致性能下降。