java多线程中的各种锁及使用场景

仅供参考

对比表

锁类型

是否可重入

是否公平

是否支持超时/中断

读写分离

适用场景

synchronized

否(JVM 优化后近似公平)

简单同步

ReentrantLock

可选

高级控制、公平性

ReentrantReadWriteLock

可选

读多写少

StampedLock

是(部分)

是(含乐观读)

高性能读多写少

原子类(CAS)

无锁并发更新(计数器等)

一、内置锁(Intrinsic Lock / Monitor Lock)

1. synchronized 关键字

  • 原理:基于 JVM 的 monitor(监视器)机制。
  • 作用范围
    • 方法级别(实例方法、静态方法)
    • 代码块(指定对象作为锁)

java

编辑

public synchronized void method() { ... } // 锁当前对象(this)

public static synchronized void staticMethod() { ... } // 锁类对象(Class)

synchronized (lockObject) { ... } // 显式指定锁对象

✅ 使用场景:

  • 简单的线程安全需求。
  • 不需要高级功能(如超时、可中断、公平性等)。
  • 性能要求不高但追求代码简洁和可靠性。

❌ 缺点:

  • 不支持尝试获取锁(tryLock)、超时、中断。
  • 无法实现读写分离(即不能区分读/写操作)。
  • 锁粒度较粗,容易造成性能瓶颈。

二、显式锁(Explicit Lock)

来自 java.util.concurrent.locks 包,主要接口为 Lock

2.1 ReentrantLock(可重入锁)

  • 特点
    • 可重入(同一线程可多次获取同一把锁)。
    • 支持公平/非公平模式(默认非公平)。
    • 支持 tryLock()lockInterruptibly()tryLock(timeout)
    • 必须手动 unlock()(通常在 finally 块中释放)。

java

编辑

ReentrantLock lock = new ReentrantLock(true); // true 表示公平锁
lock.lock();
try {
    // 临界区
} finally {
    lock.unlock();
}

✅ 使用场景:

  • 需要更灵活的锁控制(如超时、中断响应)。
  • 高并发下需要优化锁竞争(例如配合 Condition 实现生产者-消费者模型)。
  • 需要公平调度(如防止线程饥饿)。

❌ 注意:

  • 容易忘记释放锁,导致死锁或资源泄漏。
  • 性能略低于 synchronized(JVM 对 synchronized 有大量优化)。

三、读写锁(Read-Write Lock)

3.1 ReentrantReadWriteLock

  • 特点
    • 分为读锁(共享)和写锁(独占)。
    • 多个线程可同时持有读锁;但写锁是互斥的。
    • 读-读不互斥,读-写、写-写互斥。

java

编辑

ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();

// 读操作
readLock.lock();
try { /* 读 */ } finally { readLock.unlock(); }

// 写操作
writeLock.lock();
try { /* 写 */ } finally { writeLock.unlock(); }

✅ 使用场景:

  • 读多写少的场景(如缓存、配置管理)。
  • 需要提高并发读性能。

❌ 注意:

  • 写线程可能“饥饿”(尤其在高并发读时),可通过公平策略缓解。
  • 不支持锁升级(不能在持有读锁时直接获取写锁)。

四、乐观锁 vs 悲观锁(思想层面)

虽然不是具体类,但在 Java 并发中广泛应用:

4.1 悲观锁(Pessimistic Locking)

  • 假设会发生冲突,总是加锁。
  • 如:synchronizedReentrantLock

4.2 乐观锁(Optimistic Locking)

  • 假设不会冲突,只在提交时检查是否被修改。
  • 典型实现:CAS(Compare-And-Swap) + 版本号/时间戳。
应用:
  • AtomicIntegerAtomicReference 等原子类。
  • StampedLock(见下文)也支持乐观读。

五、StampedLock(Java 8 引入)

  • 特点
    • 支持三种模式:写锁、悲观读锁、乐观读
    • 乐观读不加锁,通过 stamp 验证数据是否被修改。
    • 性能优于 ReentrantReadWriteLock(尤其在读多写少且写不频繁时)。

java

编辑

StampedLock sl = new StampedLock();

long stamp = sl.tryOptimisticRead();
// 执行读操作
if (!sl.validate(stamp)) {
    // 乐观读失败,升级为悲观读
    stamp = sl.readLock();
    try {
        // 重新读
    } finally {
        sl.unlockRead(stamp);
    }
}

✅ 使用场景:

  • 极高并发读、低频写。
  • 对性能极度敏感的系统(如高性能缓存、计数器)。

❌ 注意:

  • 不可重入。
  • 不支持条件变量(Condition)。
  • 不能序列化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值