Java使用StampedLock实现高效读写功能

 更新时间:2025年01月14日 10:45:00   作者:加瓦点灯  
StampedLock 是 Java 8 引入的高性能锁,提供了三种锁模式:写锁、悲观读锁和乐观读锁,与传统的 ReentrantReadWriteLock 相比,StampedLock 更注重性能,特别适合读多写少的场景,所以本文给大家介绍了Java使用StampedLock实现高效读写功能,需要的朋友可以参考下

使用 StampedLock实现高效读写

1. 它是什么?

StampedLock 是 Java 8 引入的高性能锁,提供了三种锁模式:写锁、悲观读锁和乐观读锁。
与传统的 ReentrantReadWriteLock 相比,StampedLock 更注重性能,特别适合读多写少的场景。

  • 写锁:阻塞所有其他操作(类似独占锁)。
  • 悲观读锁:共享锁,允许多个线程读取,但会阻塞写操作。
  • 乐观读锁:一种非阻塞读操作,允许并发写操作,并在必要时验证数据一致性。

2. 它的使用场景是什么?

  • 读多写少的场景:如缓存、配置数据读取等场景,StampedLock 的乐观读锁可以显著提高性能。
  • 需要快速读锁验证的场景:在乐观读的情况下,可以验证数据的一致性并在必要时降级为悲观读锁。
  • 写锁需要优先处理的场景:避免传统读写锁中写线程因读操作而长期饥饿的问题。

3. 它有哪些 API?

核心 API

方法名称描述
writeLock()获取写锁,返回一个 stamp(锁标识)。
readLock()获取悲观读锁,返回一个 stamp(锁标识)。
tryOptimisticRead()获取乐观读锁,返回一个 stamp,非阻塞,适合快速读取。
unlockWrite(long stamp)释放写锁,需要传入获取锁时返回的 stamp。
unlockRead(long stamp)释放悲观读锁,需要传入获取锁时返回的 stamp。
validate(long stamp)验证乐观读锁期间是否有写操作发生,返回 true 表示数据未被修改。false表示数据已经被修改过

扩展 API

方法名称描述
tryWriteLock()尝试获取写锁,如果未成功立即返回。
tryReadLock()尝试获取读锁,如果未成功立即返回。
tryConvertToWriteLock(long stamp)尝试将当前锁转换为写锁,成功时返回新 stamp,否则返回 0。
tryConvertToReadLock(long stamp)尝试将当前锁转换为读锁,成功时返回新 stamp,否则返回 0。
isWriteLocked()检查当前锁是否有写锁被占用。
isReadLocked()检查当前锁是否有读锁被占用。

4. 它的使用方式

(1)写锁的使用

public void updateValue(double deltaX, double deltaY) {
    long stamp = lock.writeLock();  // 获取写锁
    try {
        x += deltaX;
        y += deltaY;
    } finally {
        lock.unlockWrite(stamp);  // 释放写锁
    }
}

(2)悲观读锁的使用

public double readValue() {
    long stamp = lock.readLock();  // 获取读锁
    try {
        return Math.sqrt(x * x + y * y);
    } finally {
        lock.unlockRead(stamp);  // 释放读锁
    }
}

(3)乐观读锁的使用

public double readValueOptimistically() {
    long stamp = lock.tryOptimisticRead();  // 获取乐观读锁
    double currentX = x, currentY = y;

    if (!lock.validate(stamp)) {  // 验证数据是否一致
        stamp = lock.readLock();  // 如果不一致,降级为悲观读锁
        try {
            currentX = x;
            currentY = y;
        } finally {
            lock.unlockRead(stamp);  // 释放悲观读锁
        }
    }

    return Math.sqrt(currentX * currentX + currentY * currentY);
}

(4)锁升级的使用

public void conditionalUpdate(double deltaX, double deltaY) {
    long stamp = lock.readLock();  // 获取悲观读锁
    try {
        if (x == 0 && y == 0) {  // 检查条件
            stamp = lock.tryConvertToWriteLock(stamp);  // 升级为写锁
            if (stamp == 0L) {  // 如果升级失败
                stamp = lock.writeLock();  // 显式获取写锁
            }
            x += deltaX;
            y += deltaY;
        }
    } finally {
        lock.unlock(stamp);  // 释放锁
    }
}

5. 它有哪些注意事项

(1)StampedLock 不可重入 StampedLock 不支持重入。如果同一线程尝试再次获取锁(无论读锁还是写锁),会导致死锁。

(2)锁释放需要传入正确的 stamp 每次加锁时都会返回一个唯一的 stamp,在释放锁时需要传入对应的 stamp,否则会抛出 IllegalMonitorStateException。

(3)写优先策略 StampedLock 优先满足写锁请求,避免了读写锁可能出现的写线程饥饿问题。

(4)线程安全 StampedLock 是线程安全的,但不支持条件变量(Condition),因此无法直接使用 wait 或 notify。

(5)适用场景 适合 读多写少 的场景。 不适合写频繁的场景,因为写锁的争用会导致性能下降。

总结

StampedLock 是 Java 并发工具库中的一颗“冷门宝石”,它通过乐观读锁提供了高效的非阻塞读机制,同时避免了写线程饥饿的问题。熟悉其 API 和使用场景,能够帮助你在性能敏感的场景中实现更高效的并发控制!

以上就是Java使用StampedLock实现高效读写功能的详细内容,更多关于Java StampedLock高效读写的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot+Spring Data JPA整合H2数据库的示例代码

    SpringBoot+Spring Data JPA整合H2数据库的示例代码

    H2数据库是一个开源的关系型数据库,本文重点给大家介绍SpringBoot+Spring Data JPA整合H2数据库的示例代码,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • 5个JAVA入门必看的经典实例

    5个JAVA入门必看的经典实例

    这篇文章主要为大家详细介绍了5个JAVA入门必看的经典实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Java实战之实现用户登录

    Java实战之实现用户登录

    这篇文章主要介绍了Java实战之实现用户登录,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • java实现浮点数转人民币的小例子

    java实现浮点数转人民币的小例子

    java实现浮点数转人民币的小例子,需要的朋友可以参考一下
    2013-03-03
  • SpringBoot项目动态指定配置文件的方法示例

    SpringBoot项目动态指定配置文件的方法示例

    SpringBoot 作为 Java 开发中一个非常流行的框架,以其简化配置和快速启动应用而闻名,在开发过程中,我们经常需要根据不同的环境来加载不同的配置文件,本文给大家介绍了SpringBoot项目动态指定配置文件的方法示例,需要的朋友可以参考下
    2024-12-12
  • java HttpClient传输json格式的参数实例讲解

    java HttpClient传输json格式的参数实例讲解

    这篇文章主要介绍了java HttpClient传输json格式的参数实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • IDEA 2022 CPU占用100%的问题及解决方法

    IDEA 2022 CPU占用100%的问题及解决方法

    这篇文章主要介绍了IDEA 2022 CPU占用100%问题及解决方法,其实解决方法很简单,只需要禁用三个插件然后重启idea即可成功解决,需要的朋友可以参考下本文
    2022-08-08
  • Java深入解析接口interface

    Java深入解析接口interface

    接口是Java中最重要的概念之一,它可以被理解为一种特殊的类,不同的是接口的成员没有执行体,是由全局常量和公共的抽象方法所组成,本文给大家介绍Java接口,感兴趣的朋友一起看看吧
    2022-06-06
  • Mybatis中返回Map的实现

    Mybatis中返回Map的实现

    这篇文章主要介绍了Mybatis中返回Map的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 使用RedisAtomicLong优化性能问题

    使用RedisAtomicLong优化性能问题

    这篇文章主要介绍了使用RedisAtomicLong优化性能问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11

最新评论