Java Lock常用的锁有哪些?(新手必看)
Lock 框架是指 java.util.concurrent.locks 包中的一系列类和接口,它们是 JUC 的一部分。这些类和接口提供了在多线程程序中管理锁定的各种机制,专门用于处理线程之间的同步问题。
使用 Lock 框架可以在多线程环境下更灵活地控制锁定和解锁。Lock 接口提供了比传统的 synchronized 关键字更丰富的锁操作,包括非块结构的锁定、非阻塞地获取锁、可中断地获取锁以及在给定的最大时间范围内获取锁等多种方式。
在 java.util.concurrent.locks 包中有两个重要的接口,分别为 Lock 和 ReadWriteLock,它们代表了两种类型的锁,Lock 提供了基础的互斥锁功能,而 ReadWriteLock 针对读写操作提供了更细粒度的控制。
下面我们列举几种 Lock 框架常用的锁及其优缺点。
比如,它具有无条件的、可轮询的、定时的,以及可中断的锁获取操作,并且支持选择公平锁或非公平锁。
ReentrantLock 的优点如下:
ReentrantLock 的缺点如下:
ReentrantReadWriteLock 的优点如下:
ReentrantReadWriteLock 的缺点如下:
StampedLock 的优点如下:
StampedLock 的缺点如下:
除上述提到的这些锁,还有 LockSupport 工具类,尽管 LockSupport 不是锁,但它是实现锁和其他同步工具的底层机制。它提供了基本的挂起和唤醒线程的功能,比如park() 和 unpark(Thread thread)。
还有 Condition,它需要与 ReentrantLock 配合使用,每个 Condition 实例都与一个锁绑定,提供对该锁进行精细控制的能力。
总之,JUC 中的这些锁都是基于 AQS 实现的,提供了比传统 synchronized 关键字更灵活、更强大的并发编程能力,允许我们实现更复杂的并发逻辑和数据结构。然而,这些额外的功能和灵活性带来了更高的复杂度和使用上的挑战。
选择哪种锁,取决于具体的应用场景以及对性能、公平性、可重入性、读写分离等因素的需求。
使用 Lock 框架可以在多线程环境下更灵活地控制锁定和解锁。Lock 接口提供了比传统的 synchronized 关键字更丰富的锁操作,包括非块结构的锁定、非阻塞地获取锁、可中断地获取锁以及在给定的最大时间范围内获取锁等多种方式。
在 java.util.concurrent.locks 包中有两个重要的接口,分别为 Lock 和 ReadWriteLock,它们代表了两种类型的锁,Lock 提供了基础的互斥锁功能,而 ReadWriteLock 针对读写操作提供了更细粒度的控制。
下面我们列举几种 Lock 框架常用的锁及其优缺点。
Lock ReentrantLock
ReentrantLock 实现了 Lock 接口的可重入锁。它具有与使用 synchronized 关键字相同的一些基本行为和语义,但与 synchronized 关键字相比,它提供了更多的高级功能。比如,它具有无条件的、可轮询的、定时的,以及可中断的锁获取操作,并且支持选择公平锁或非公平锁。
ReentrantLock 的优点如下:
- 灵活性高:与 synchronized 关键字相比,它提供了更多的高级功能,如尝试锁定(使用 tryLock() 实现)、带超时的锁定等;
- 可重入:线程可以重复获取已经持有的锁,避免死锁;
- 支持选择公平锁:可以设置为公平锁(先到先得),避免饥饿。
ReentrantLock 的缺点如下:
- 性能损耗大:在高竞争环境下,管理锁的开销比较大;
- 易用性不足:需要手动释放锁,忘记释放锁可能导致死锁。
Lock ReentrantReadWriteLock
ReentrantReadWriteLock 实现了 ReadWriteLock 接口的读锁和写锁,它维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。读锁可以由多个读线程同时持有,而写锁是独占的。ReentrantReadWriteLock 的优点如下:
- 能够提高性能:通过分离读锁和写锁,允许多个读线程同时访问,提高了并发性能;
- 灵活性高:适用于读多写少的场景。
ReentrantReadWriteLock 的缺点如下:
- 锁升级问题:读锁无法直接升级为写锁;
- 开销较大:管理读锁和写锁的开销相对较大。
Lock StampedLock
StampedLock 提供了一种锁机制,用于管理对一个变量的读写访问,相比 ReentrantReadWriteLock,它提供了更高的并发性。除了支持读锁和写锁,它还支持乐观读锁机制。乐观读允许在没有完全锁定的情况下进行读取,并且支持将乐观读锁转换为读锁或写锁。StampedLock 的优点如下:
- 高性能:它被设计用于解决 ReentrantReadWriteLock 的性能问题,并且通常表现更好;
- 支持锁升级和降级:提供了从读锁到写锁的转换方法,以及锁的降级方法;
- 支持乐观读模式:乐观读模式是一种不完全锁定的读模式,可以提高系统的整体吞吐量。
StampedLock 的缺点如下:
- 不支持条件变量;
- 锁的获取方法不能被中断;
- API 比较复杂,不当的使用可能导致死锁。
除上述提到的这些锁,还有 LockSupport 工具类,尽管 LockSupport 不是锁,但它是实现锁和其他同步工具的底层机制。它提供了基本的挂起和唤醒线程的功能,比如park() 和 unpark(Thread thread)。
还有 Condition,它需要与 ReentrantLock 配合使用,每个 Condition 实例都与一个锁绑定,提供对该锁进行精细控制的能力。
总之,JUC 中的这些锁都是基于 AQS 实现的,提供了比传统 synchronized 关键字更灵活、更强大的并发编程能力,允许我们实现更复杂的并发逻辑和数据结构。然而,这些额外的功能和灵活性带来了更高的复杂度和使用上的挑战。
选择哪种锁,取决于具体的应用场景以及对性能、公平性、可重入性、读写分离等因素的需求。