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高效读写的资料请关注脚本之家其它相关文章!

相关文章

  • java web SpringMVC后端传json数据到前端页面实例代码

    java web SpringMVC后端传json数据到前端页面实例代码

    本篇文章主要介绍了java web SpringMVC后端传json数据到前端页面实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • SpringBoot中验证用户上传的图片资源的方法

    SpringBoot中验证用户上传的图片资源的方法

    这篇文章主要介绍了在SpringBoot中验证用户上传的图片资源,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • maven私有镜像仓库nexus部署使用

    maven私有镜像仓库nexus部署使用

    Nexus在企业开发中还是比较常用的私有仓库管理工具,本文主要介绍了maven私有镜像仓库nexus部署使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-07-07
  • 你要知道IDEA的这些必备插件

    你要知道IDEA的这些必备插件

    这篇文章主要介绍了你要知道IDEA的这些必备插件,文中有非常详细的图文示例及代码,对正在使用IDEA的小伙伴们有很好的帮助哟,需要的朋友可以参考下
    2021-05-05
  • Java 任务调度框架 Quartz实操

    Java 任务调度框架 Quartz实操

    这篇文章主要介绍了Java 任务调度框架 Quartz,Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。,下面我们来学习一下关于 Quartz更多的详细内容,需要的朋友可以参考一下
    2021-12-12
  • SpringMvc配置静态资源访问路径的实现

    SpringMvc配置静态资源访问路径的实现

    本文主要介绍了SpringMvc配置静态资源访问路径的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Spring Data JPA 整合QueryDSL的使用案例

    Spring Data JPA 整合QueryDSL的使用案例

    QueryDSL 是一个用于构建类型安全的 SQL 查询的 Java 库,它的主要目标是简化在 Java 中构建和执行 SQL 查询的过程,同时提供类型安全性和更好的编码体验,对Spring Data JPA 整合QueryDSL使用案例感兴趣的朋友跟随小编一起看看吧
    2023-08-08
  • spring boot tomcat版本升级的实现示例

    spring boot tomcat版本升级的实现示例

    本文主要介绍了spring boot tomcat版本升级的实现示例,将tomcat升级一个小版本升级到9.0.44版本,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • Java 面向对象通过new揭开对象实例化

    Java 面向对象通过new揭开对象实例化

    各位铁汁们大家好呀,我们上次博客讲了,通过 Student student1 = new Student();就可以实例化一个对象,这个对象就有Student类中的所以成员变量。可是 对象student1 和 类Student到底是怎样建立联系的,在内存中到底发生了什么
    2022-04-04
  • java生成jar包的方法

    java生成jar包的方法

    这篇文章主要介绍了java生成jar包的方法,对Java生成jar包的具体步骤及方法进行了较为详细的描述,是非常实用的技巧,需要的朋友可以参考下
    2014-09-09

最新评论