Java 标准库 API 系列之 StampedLock

本贴最后更新于 720 天前,其中的信息可能已经东海扬尘

在学习蚂蚁金服实现的 Raft 算法实现 sofa-jraft 项目中第一次接触到这个锁。jraft 使用 StampedLock 来实现对于 raft group 的路由信息的线程安全。

StampedLock 是 Java 8 中引入的新的锁机制,它支持三种模式的访问控制,分别是读模式、写模式和乐观读模式,它可以在高并发的情况下提供更好的性能和吞吐量。

在 StampedLock 中,每个线程都需要获取一个戳(stamp)来进行读或写操作,这个戳是一个 64 位的数字,其中高 16 位代表一个版本号,低 48 位代表一个序号。线程可以使用 tryOptimisticRead()方法来获取一个乐观读锁,这种方式不会阻塞线程,只是获取一个戳,如果获取到的戳发生了变化,就意味着有其他线程已经修改了共享资源,这时候需要重新获取锁。

StampedLock 还支持读锁和写锁。读锁是共享锁,多个线程可以同时持有读锁,并发地读取共享资源,而写锁是独占锁,只有一个线程可以持有写锁,其他线程需要等待写锁释放才能继续执行。

StampedLock 的优势在于,对于读多写少的场景,使用乐观读锁可以避免大量线程阻塞,提高系统的吞吐量;对于写操作比较频繁的场景,使用 StampedLock 可以减少锁的竞争,提高系统的性能。

API

StampedLock 有三种锁的获取方式:

  1. 读锁(readLock()):多个线程可以同时持有读锁,只要没有线程持有写锁。读锁是乐观的且不可重入的。通过调用 tryOptimisticRead()方法获取读锁,如果锁可用,会返回一个非零的标记(stamp)。
  2. 写锁(writeLock()):只有一个线程可以持有写锁,它排除所有的读锁和写锁。写锁是悲观的且可重入的。通过调用 writeLock()方法获取写锁。
  3. 乐观读锁(Optimistic Read Lock):乐观读锁是一种特殊的读锁,它允许其他线程在获取读锁之前修改共享数据,但在验证阶段检测到数据被修改时,需要重新获取锁。乐观读锁的获取方式是调用 tryOptimisticRead()方法,如果锁可用,会返回一个非零的标记(stamp)。

下面是一个简单的 StampedLock 的使用示例:

import java.util.concurrent.locks.StampedLock; public class Point { private double x; private double y; private final StampedLock lock = new StampedLock(); public void setPoint(double x, double y) { long stamp = lock.writeLock(); try { this.x = x; this.y = y; } finally { lock.unlockWrite(stamp); } } public double distanceFromOrigin() { long stamp = lock.tryOptimisticRead(); double currentX = x; double 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); } }

在上述示例中,setPoint() 方法使用写锁来更新坐标。写锁是 排他锁,当一个线程获取写锁时,其他线程无法获取读锁或写锁。

distanceFromOrigin() 方法使用乐观读锁尝试获取点的当前坐标,并计算点到原点的距离。如果乐观读锁验证失败(即期间有写操作),则通过获取悲观读锁来重新读取坐标。

这个例子展示了 StampedLock 的乐观读锁和悲观写锁的使用方式,通过合理地选择锁的模式,可以提供更高的并发性能,并且允许读操作和写操作同时进行,而不会相互阻塞。

校验是否有写操作 是如何判断的

StampedLock 的写锁有一个版本号,读锁没有版本号。因此,StampedLock 可以通过判断当前读锁的版本号是否等于写锁的版本号来检查是否存在写锁。如果版本号相同,说明当前存在写锁,反之,则没有写锁。需要注意的是,在使用 StampedLock 时,如果读锁和写锁是在不同的线程中获取的,那么在判断是否存在写锁时可能存在一定的延迟,因为写锁的版本号可能已经变化,但是读锁的版本号还没有更新。因此,在这种情况下,可能会出现一定的误判。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 626 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 1 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 648 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 635 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 79 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖 • 1 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    336 引用 • 324 回帖 • 1 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    952 引用 • 944 回帖 • 1 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    171 引用 • 1533 回帖
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 90 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 2 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 58 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖 • 7 关注
  • AWS
    11 引用 • 28 回帖 • 5 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 255 关注
  • gRpc
    11 引用 • 9 回帖 • 93 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    227 引用 • 476 回帖
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 577 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 6 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    325 引用 • 1395 回帖 • 1 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 740 关注