Java并发锁机制比较:LockSupport、ReentrantLock、ReentrantReadWriteLock、StampedLock

1. LockSupport

特点

  • 最底层的线程阻塞/唤醒工具

  • 不依赖锁对象,直接操作线程

  • 提供许可证(permit)机制(类似信号量,但最多只有1个)

  • 不可重入

核心方法

  • park() - 阻塞当前线程

  • unpark(Thread thread) - 唤醒指定线程

  • parkNanos(long nanos) - 带超时的阻塞

优势

  • 比Object.wait()/notify()更灵活

  • 不会导致死锁(因为没有锁的获取顺序问题)

  • 可先unpark后park(许可证机制)

使用场景

  • 构建高级同步工具的基础

  • 需要精确控制线程阻塞/唤醒的场景

  • AQS(AbstractQueuedSynchronizer)的实现基础

2. ReentrantLock

特点

  • 可重入互斥锁

  • 提供公平锁和非公平锁两种模式

  • 支持尝试获取锁(tryLock)

  • 支持可中断的锁获取

  • 支持条件变量(Condition)

核心方法

  • lock()unlock()

  • tryLock()tryLock(long timeout, TimeUnit unit)

  • lockInterruptibly()

  • newCondition()

优势

  • 比synchronized更灵活

  • 可中断的锁获取

  • 支持多个条件变量

  • 可设置公平性

使用场景

  • 需要可中断锁获取的场景

  • 需要尝试获取锁的场景

  • 需要多个条件变量的场景

  • 需要公平锁的场景

3. ReentrantReadWriteLock

特点

  • 读写锁分离:读锁共享,写锁独占

  • 可重入

  • 支持公平和非公平模式

  • 支持锁降级(写锁降级为读锁)

  • 不支持锁升级(读锁升级为写锁)

核心结构

  • ReadLock - 共享读锁

  • WriteLock - 独占写锁

优势

  • 读多写少场景性能优于互斥锁

  • 减少读操作间的竞争

使用场景

  • 读操作远多于写操作的场景

  • 需要保证写操作的可见性

  • 缓存系统实现

注意事项

  • 写锁饥饿问题(公平模式下可缓解)

  • 不适合写多读少的场景

4. StampedLock

特点

  • JDK8新增的锁机制

  • 三种访问模式:

    • 写锁(独占,类似ReentrantLock)

    • 悲观读锁(共享,类似ReentrantReadWriteLock的读锁)

    • 乐观读(无锁,类似volatile读)

  • 不可重入

  • 不支持条件变量

  • 提供锁转换功能

核心方法

  • writeLock()tryWriteLock()

  • readLock()tryReadLock()

  • tryOptimisticRead()

  • validate(long stamp) - 验证乐观读期间是否有写操作

优势

  • 乐观读模式提供更高的并发度

  • 比ReentrantReadWriteLock更高的吞吐量

  • 支持锁转换(如读锁转写锁)

使用场景

  • 读多写少且对数据一致性要求不严格的场景

  • 需要极高读性能的场景

  • 适合简单的数据模型

注意事项

  • 使用较复杂,容易出错

  • 乐观读后需要验证

  • 不支持重入和条件变量

对比总结

特性LockSupportReentrantLockReentrantReadWriteLockStampedLock
锁类型线程阻塞工具互斥锁读写分离锁多模式锁
重入性不支持支持支持不支持
公平性可配置可配置不可配置
条件变量支持支持不支持
读写分离读锁/写锁读锁/写锁/乐观读
性能读多写少场景高极高(乐观读模式)
复杂性
适用场景构建同步工具基础通用互斥需求读多写少极高读性能需求

选择建议

  1. 构建自定义同步器:LockSupport

  2. 通用互斥需求:ReentrantLock

  3. 典型读多写少:ReentrantReadWriteLock

  4. 极高读性能需求:StampedLock

  5. 需要条件变量:ReentrantLock或ReentrantReadWriteLock

  6. 需要乐观读:StampedLock

注意事项

  1. 锁的粒度:尽量减小锁的持有时间和范围

  2. 死锁预防:避免嵌套锁,按固定顺序获取锁

  3. 性能考量:在高竞争环境下测试不同锁的性能

  4. StampedLock陷阱:乐观读后必须验证,且容易误用

  5. 读写锁适用性:评估读写比例,不适用于写多场景

代码示例

StampedLock乐观读示例

class Point {
    private double x, y;
    private final StampedLock sl = new StampedLock();
    
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
        }
    }
    
    double distanceFromOrigin() {
        long stamp = sl.tryOptimisticRead(); // 乐观读
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) { // 检查是否有写操作
            stamp = sl.readLock(); // 获取悲观读锁
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}

在线求职,坐标山西太原,18935138820,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值