码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • java并发编程-StampedLock高性能读写锁


    目录
    • 一、读写锁
    • 二、悲观读锁
    • 三、乐观读
    • 欢迎关注我的博客,更多精品知识合集

    一、读写锁

    在我的《java并发编程》上一篇文章中为大家介绍了《ReentrantLock读写锁》,ReentrantReadWriteLock可以保证最多同时有一个线程在写数据,或者可以同时有多个线程读数据,但读写不能同时进行。

    比如你正在做的是日志,有一个线程正在做写操作,但是在写日志的时候你可能需要把日志集中转移到集中管理日志服务,但是此时读线程不能读数据(因为无法获取读锁)。面对这个需求,ReentrantReadWriteLock显然不是我们的解决方案,我们希望:最多一个线程在进行写操作(加写锁),但是同时允许多个线程进行读操作(加读锁),解决方案是StampedLock。

    二、悲观读锁

    StampedLock 同样可以实现写锁和读锁的功能,Stamped在英文中有印章的含义,对于StampedLock大家可以这么理解,使用一个印章加锁,必须使用该印章解锁。

    public class TestStampedLock {
        Map<String,String> map = new HashMap<>();
        //锁对象
        private StampedLock lock = new StampedLock();
     
        //写操作函数
        public void put(String key, String value){
            long stamp = lock.writeLock(); //加写锁
            try {
                map.put(key, value); //写操作
            } finally {
                lock.unlockWrite(stamp);  //释放写锁
            }
        }
     
        public String get(String key) {
            long stamp = lock.readLock(); //加读锁
            try {
                return map.get(key); //读操作
            } finally {
                lock.unlockRead(stamp); //释放读锁
            }
        }
    }
    

    上文中的读锁readLock,在StampedLock模式中被称为悲观读锁,之所以叫做悲观读锁是和StampedLock支持的另一种模式“乐观读”相对应的。
    写锁、悲观读锁的语义和 ReadWriteLock 的写锁、读锁的语义基本是一致的,允许多个线程同时获取悲观读锁,但是只允许一个线程获取写锁,写锁和悲观读锁是互斥的。多线程环境下,写操作的同时不能读。所以到这里为止,StampedLock与ReadWriteLock并没有很大的区别。

    三、乐观读

    需要注意的是,这里我写的是乐观读,而不是乐观读锁,因为乐观读是不加锁的。通过tryOptimisticRead()函数获取一个stamp,这里的tryOptimisticRead() 就是乐观读,乐观读因为没有加锁,所以读取数据的性能会更高一点。即:已经有写操作线程加锁的同时,仍然允许读操作线程继续进行。

    如果你的读写操作有比较强的时间点数据一致性要求,即:同一个时间点读操作读到的数据,一定与该时间点写操作保持数据一致性。那么,你就需要进行validate校验,stamp此时可以理解为一个版本号,如果写操作版本为2,读操作版本为1,说明你读到的数据不是最新的。你需要去读取最新版本的数据(版本号为2),所以需要升级为悲观读锁,代码如下:

    public String readWithOptimisticLock(String key) {
        long stamp = lock.tryOptimisticRead(); //乐观读
        String value = map.get(key); //读取数据
     
        if(!lock.validate(stamp)) {  //校验数据是否是最新版本
            stamp = lock.readLock();  //如果不是,升级为悲观读锁
            try {
                return map.get(key);
            } finally {
                lock.unlock(stamp);               
            }
        }
        return value;
    }
    

    欢迎关注我的博客,更多精品知识合集

    本文转载注明出处(必须带连接,不能只转文字):字母哥博客 - zimug.com

    觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力!。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

    • 《kafka修炼之道》
    • 《手摸手教你学Spring Boot2.0》
    • 《Spring Security-JWT-OAuth2一本通》
    • 《实战前后端分离RBAC权限管理系统》
    • 《实战SpringCloud微服务从青铜到王者》
  • 相关阅读:
    PyTorch构建训练集
    4G网关BL100链接私有云平台教程
    使用NSSM将.exe程序安装成windows服务
    测量工具----示波器
    建模杂谈系列177 APIFunc继续实践-比对研究
    快应用开发初体验
    Springboot 拦截器,拦截所有请求,判断是否登录,验证权限
    海格里斯四向穿梭车|为何越来越多的仓库选择使用四向穿梭车立体库?
    硬件开发笔记(十七):RK3568底板电路串口、485、usb原理图详解
    websocket多线程发送消息报错TEXT_PARTIAL_WRITING--自旋锁替换synchronized独占锁的使用案例
  • 原文地址:https://www.cnblogs.com/zimug/p/16275645.html
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号