首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java中有多少种类型的锁?

在 Java 中,锁的类型可以从多个维度进行分类。

一、根据锁的性质划分

1. 内部锁(Intrinsic Lock)

Java 内置的锁机制,通常使用 synchronized 关键字实现。

每个对象都有一个内部锁,线程可以通过 synchronized 进入临界区。

特点:自动释放,不需要手动解锁。

2. 显示锁(Explicit Lock)

常用类有 ReentrantLock、ReadWriteLock 等。

特点:提供更灵活的锁机制,可以实现可重入锁、读写锁等,支持公平性控制。

3. 自旋锁(Spin Lock)

通过自旋等待(即不断循环尝试获取锁)而不是阻塞线程来实现的锁。

Java 本身没有直接的自旋锁类,但可以通过 Atomic 操作和 CAS 实现。

特点:适合短时间所持有的场景,减少线程上下文切换的开销。

4. 可重入锁(Reentrant Lock)

Java 提供的 ReentrantLock 类是典型的可重入锁。

特点:同一个线程可以多次获得同一把锁,避免死锁。

5. 读写锁(ReadWriteLock)

读写分离的锁,通过 ReadWriteLock 接口实现,主要实现类是 ReentrantReadWriteLock。

特点:允许多个线程同时读,但写操作需要独占锁,适用于读多写少的场景。

6. 公平锁和非公平锁(Fair and Unfair Lock)

ReentrantLock 可以配置为公平锁或非公平锁。

公平锁遵循先进先出原则,非公平锁则不保证顺序。

特点:公平锁减少了线程饥饿,但性能可能稍差;非公平锁可能提高性能,但有可能导致线程饥饿。

7. 偏向锁(Biased Locking)、轻量级锁(Lightweight Locking)和重量级锁(Heavyweight Locking)

这些是 JVM 优化 synchronized 锁的几种状态。

偏向锁:当只有一个线程访问同步块时,锁会偏向该线程,减少加锁开销。

轻量级锁:在没有竞争时,会使用 CAS 操作代替传统的阻塞操作。

重量级锁:当有多个线程竞争时,锁会膨胀为重量级锁,通过操作系统的线程调度来管理。

8. 条件锁(Condition)

与 ReentrantLock 配合使用的锁,提供类似 Object.wait() 和 notify() 的功能。

常用类为 Condition。

特点:允许更灵活的线程等待和唤醒机制,适合复杂的同步需求。

9. 悲观锁(Pessimistic Lock)和乐观锁(Optimistic Lock)

悲观锁:假设会发生并发冲突,直接加锁保护资源。

乐观锁:假设不会发生并发冲突,采用 CAS 等无锁机制,通常使用 Atomic 类实现。

特点:悲观锁适合高竞争环境,乐观锁适合低冲突场景。

10. 信号量(Semaphore)

特点:不像普通的锁只能限制一个线程,可以设定多个许可。

11. 栅栏(Barrier)

用于多个线程间的协调和同步,例如 CyclicBarrier、CountDownLatch。

特点:适合一组线程需要在特定点上同步执行的场景。

12. 乐观锁(Optimistic Lock)

不是基于锁实现的,而是通过无锁的机制来确保并发安全。

常用 Atomic 类(如 AtomicInteger、AtomicReference)和 CAS 操作。

13. StampedLock

JDK 8 引入的锁,用于替代传统的读写锁,支持三种锁模式:写锁、悲观读锁和乐观读锁。

特点:乐观读锁允许读操作在没有竞争的情况下尽可能高效。

Java 中的锁机制种类丰富,涵盖了各种并发场景的需求。具体使用哪种锁,需要根据程序的并发特性、性能需求、资源访问模式等来选择。

二、根据锁的机制划分

14. 线程局部锁(ThreadLocal)

通过 ThreadLocal 类实现,使每个线程都能拥有自己的独立副本,从而避免竞争。

特点:不是真正的“锁”,但可以在需要隔离共享数据的情况下,避免线程间的同步开销。

15. 无锁数据结构(Lock-Free Data Structures)

使用 CAS 和原子类实现的无锁数据结构,如 ConcurrentLinkedQueue、ConcurrentSkipListMap。

特点:在多线程环境下提供更好的性能,避免传统锁的开销。

16. 协作式锁(Cooperative Locking)

通过非阻塞操作和信号的协作来实现线程同步,例如在 I/O 操作时,线程在等待时不持有锁。

特点:可用于减少阻塞,提升系统的响应性,但通常更复杂。

17. 偏好锁(Preferential Locking)

适用于让某些线程优先获取锁,以保证重要线程的高优先级,通常通过调度器和锁机制的结合来实现。

特点:适用于对响应时间有严格要求的应用。

18. 分段锁(Striped Locking)

一种分段锁机制,通过将数据分段并为每段加独立锁,降低锁冲突。

常用于 ConcurrentHashMap,有效分散锁的竞争压力。

特点:适合大量数据并发访问场景,减少锁的竞争。

19. 信号与事件锁

特点:适合复杂的线程协作或阶段性执行场景。

这些额外的锁机制扩展了 Java 的并发模型,使其能够在多种应用场景下优化并发性能。选择合适的锁类型取决于应用需求、线程访问模式和性能要求。

三、其他锁概念

在 Java 中,除了前面提到的各种锁之外,还存在一些特殊或实验性的锁机制和概念,这些主要用于高级或特定的场景。以下是一些少见但可以在并发编程中使用到的锁:

20. Read Mostly Lock

是一种针对读操作优化的锁机制。一般在读操作远多于写操作的场景中,提供了比传统读写锁更高效的读性能。

特点:通常通过将读操作分散在多个锁上来实现,从而减少锁的竞争。

21. 双重检查锁(Double-Checked Locking)

在懒加载单例模式中常用,通过两次检查是否需要加锁来避免不必要的同步。

特点:减小锁的范围,提升性能。但要注意使用 volatile 修饰实例变量以确保线程安全。

22. 自适应锁(Adaptive Locking)

一种动态调整锁策略的锁机制,根据锁的竞争程度调整为自旋锁或阻塞锁。

特点:适用于线程竞争程度不稳定的场景,可以在 JVM 内部优化锁的使用。

23. 手动锁膨胀和收缩(Manual Lock Inflation/Deflation)

在 Java 虚拟机中,锁在有竞争时会自动膨胀为重量级锁,但可以手动控制锁的膨胀和收缩以优化性能。

特点:多用于性能调优,适合非常高并发和高性能要求的场景。

24. 虚拟线程锁(Virtual Thread Locking)

Java 19 引入了虚拟线程(Project Loom),使得每个虚拟线程有自己的栈空间。虚拟线程的锁机制不同于普通线程,适用于高并发非阻塞场景。

特点:适合使用虚拟线程的高并发 I/O 操作,不会像传统线程一样受到阻塞的影响。

25. 基于硬件的锁(Hardware Lock Elision, HLE)

在一些高性能服务器或处理器上支持的锁机制,通过硬件级别实现锁省略(Elision)。

特点:非常高效,但依赖硬件支持,通常在 JVM 内部实现。

26. 轻量级并行锁(Lightweight Parallel Locks)

一种通过拆分资源来减少锁竞争的方法,使多个线程可以并行地访问不同的资源部分。

特点:适合资源可以分割的场景,如数据分块处理。

Java 的锁机制在不断进化,JVM 和并发包的更新也在尝试加入更多的并发控制方案。这些特殊的锁机制较为少见,通常在高性能、高并发或特定硬件环境中使用。对于一般应用场景,通常不需要使用到这些锁,但在性能调优或特殊需求时,可以考虑这些高级锁机制。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O8ZvNzTTaLiTGB3z8kuX4d2g0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券