Java乐观锁的实现原理和典型案例

这篇具有很好参考价值的文章主要介绍了Java乐观锁的实现原理和典型案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

乐观锁,Java 并发编程,chat-gpt

Java乐观锁的实现原理

什么是乐观锁?

在并发编程中,多个线程同时对同一资源进行操作时,需要使用锁来保证数据的一致性。
乐观锁与悲观锁是两种不同的锁机制。
悲观锁会在整个操作期间占用资源的独占性,以保证数据的一致性,而乐观锁则是基于版本号或时间戳的机制,在操作前做一个乐观的估计,如果操作成功,则版本号加1,如果失败,则重试。因为乐观锁不需要在整个操作期间占用资源的独占性,所以可以提高并发性。

Java中乐观锁的实现方式

Java中的乐观锁主要有两种实现方式:CAS(Compare and Swap)和版本号控制。

CAS

CAS是实现乐观锁的核心算法,它通过比较内存中的值是否和预期的值相等来判断是否存在冲突。如果存在,则返回失败;如果不存在,则执行更新操作。

CAS 它包含了 3 个参数:V(需要更新的变量)、E(预期值)和 N(最新值)。只有当需要更新的变量等于预期值时,需要更新的变量才会被设置为最新值,如果更新值和预期值不同,则说明已经有其它线程更新了需要更新的变量,此时当前线程不做操作,返回 V 的真实值。

Java中提供了AtomicInteger、AtomicLong、AtomicReference等原子类来支持CAS操作。

下面是一个简单的CAS示例:

代码

public class Counter {
    private AtomicInteger value = new AtomicInteger(0);

    public void increment() {
        int expect;
        int update;

        do {
            expect = value.get();
            update = expect + 1;
        } while (!value.compareAndSet(expect, update));
    }
}

在这个示例中,increment()方法会不断地执行CAS操作,直到更新成功为止。

版本号控制

版本号控制是乐观锁的另一种实现方式。

每当一个线程要修改数据时,都会先读取当前的版本号或时间戳,并将其保存下来。线程完成修改后,会再次读取当前的版本号或时间戳,如果发现已经变化,则说明有其他线程对数据进行了修改,此时需要回滚并重试。

下面是一个简单的版本号控制示例:

代码

public class Counter {
    private int value = 0;
    private int version = 0;

    public void increment() {
        int currentVersion;
        int currentValue;

        do {
            currentVersion = version;
            currentValue = value;
            currentValue++;
        } while (currentVersion != version);

        value = currentValue;
        version = currentVersion + 1;
    }
}

在这个示例中,increment()方法会不断地执行循环,直到当前的版本号与保存的版本号相同为止。如果版本号不同,则说明有其他线程修改了数据,此时需要回滚并重试。

Java中乐观锁的案例

ConcurrentHashMap

ConcurrentHashMap是Java中的一个线程安全的哈希表实现,它使用分离锁(Segment)来保证线程安全。每个Segment都是一个独立的哈希表,每个操作只锁定相关的Segment,因此可以支持更高的并发性。

ConcurrentHashMap使用了一种基于CAS的技术来实现乐观锁,它通过比较当前的value和预期的value是否相等来判断是否存在冲突。如果存在,则返回失败;如果不存在,则执行更新操作。

LongAdder

在 JDK1.8 中,Java 提供了一个新的原子类 LongAdder。LongAdder 在高并发场景下会比 AtomicInteger 和 AtomicLong 的性能更好,代价就是会消耗更多的内存空间。

LongAdder 的原理就是降低操作共享变量的并发数,也就是将对单一共享变量的操作压力分散到多个变量值上,将竞争的每个写线程的 value 值分散到一个数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的 value 值进行 CAS 操作,最后在读取值的时候会将原子操作的共享变量与各个分散在数组的 value 值相加,返回一个近似准确的数值。

数据库并发控制

在日常开发中,使用乐观锁最常见的场景就是数据库的更新操作了。

为了保证操作数据库的原子性,我们常常会为每一条数据定义一个版本号,并在更新前获取到它,到了更新数据库的时候,还要判断下已经获取的版本号是否被更新过,如果没有,则执行该操作。

总结

在Java中,并发编程的时候可以使用Synchronized 和 Lock 实现的同步锁机制,但是两种同步锁都属于悲观锁。

悲观锁在高并发的场景下,激烈的锁竞争会造成线程阻塞,大量阻塞线程会导致系统的上下文切换,增加系统的性能开销,这个时候乐观锁就是我们可以考虑的一种方案。

当然CAS 乐观锁在平常使用时比较受限,它只能保证单个变量操作的原子性,当涉及到多个变量时,CAS 就无能为力了。

好了,以上就是今天分享的全部内容,enjoy~ 欢迎关注我的微信公众号【AI黑板报】

本文由博客一文多发平台 OpenWrite 发布!文章来源地址https://www.toymoban.com/news/detail-528159.html

到了这里,关于Java乐观锁的实现原理和典型案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python深度学习026:基于Pytorch的典型循环神经网络模型RNN、LSTM、GRU的公式及简洁案例实现(官方)

    循环神经网络(也有翻译为递归神经网络)最典型的三种网络结构是: RNN(Recurrent Neural Network,循环神经网络) LSTM(Long Short-Term Memory,长短期记忆网络) GRU(Gate Recurrent Unit,门控循环单元) 理解参数的含义非常重要,否则,你不知道准备什么维度的输入数据送入模型 先

    2023年04月22日
    浏览(40)
  • C#代码重构的几个典型案例

    前段时间小编检查同事代码,发现居然写的太复杂看不太懂,代码命名不规范,重复冗长代码一堆,这时候就可以通过重构来改进代码的质量。代码重构是提高代码质量和可维护性的关键过程,它旨在通过优化代码结构和设计来提高代码的可读性、可理解性和可扩展性。本文

    2024年02月16日
    浏览(34)
  • 【典型案例】解决idea打不开项目的问题

    前言 今天在使用工作过程中,遇到了一个idea开发工具先关的问题,也是因为解决这个问题耽误了正常搬砖的时间,同时也由于远程办公网速比较卡的原因,导致心情比较心烦气躁,所有针对这个心烦的问题,在这里总结一下,给后续自己提个醒; 问题描述 : 在正常工作中

    2024年02月07日
    浏览(43)
  • 【项目实战典型案例】23.部分服务总是频繁出现掉线情况

    因为某些特殊原因需要把nacos迁移到另一个版本的nacos(我迁的是nacos2.0.2版本.) 迁移完成后,Nacos注册中心有一个微服务有多台实例的时候,点击一个实例下线操作,报错 caused: errCode: 500, errMsg: do metadata operation failed ;caused:com.alibaba.nacos.consistency.exception.ConsistencyException:com.alibaba.

    2024年02月07日
    浏览(36)
  • 云起无垠典型案例入选《2023软件供应链安全洞察》报告

    近日,历时6个月,由ISC编制的《2023软件供应链安全洞察》报告(以下简称《报告》)正式对外发布。《报告》围绕软件供应链安全现状、技术内核、治理指南、落地实践展开,以期为行业从业者提供有价值的信息和洞见,帮助整个行业在应对软件供应链安全挑战的道路上迈

    2024年02月07日
    浏览(46)
  • 【项目实战典型案例】05.前后端分离的好处(发送调查问卷)

      以下流程图是给用户发送调查问的整体流程,将不必要的业务逻辑放到前端进行处理。这样导致逻辑混乱难以维护。前后端分离的其中一个目的是将功能的样式放在了前端将功能的业务逻辑放到了后端来处理。   明确业务逻辑,对于业务逻辑的明确可以使用UML图的方式

    2024年02月11日
    浏览(43)
  • Spark大数据处理讲课笔记---Spark RDD典型案例

    利用RDD计算总分与平均分 利用RDD统计每日新增用户 利用RDD实现分组排行榜 针对成绩表,计算每个学生总分和平均分   读取成绩文件,生成lines;定义二元组成绩列表;遍历lines,填充二元组成绩列表;基于二元组成绩列表创建RDD;对rdd按键归约得到rdd1,计算总分;将rdd1映射

    2024年02月06日
    浏览(51)
  • 遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型

    详情点击链接:遥感云大数据在灾害、水体与湿地领域典型案例实践及GPT模型 第一: 基础 一: 平台及基础 开发平台 ·GEE平台及典型应用案例; ·GEE开发环境及常用数据资源; ·ChatGPT、文心一言等GPT模型 ·JavaScript基础; ·GEE遥感云重要概念与典型数据分析流程;     ·G

    2024年02月12日
    浏览(54)
  • 华为AR路由器 典型配置案例——以太网交换

    目录 Eth-Trunk 例:配置三层链路聚合 组网需求 操作步骤 检查配置结果 配置脚本 VLAN 举例:配置基于接口划分VLAN,实现同一VLAN内的互通(同设备) 组网需求 操作步骤 检查配置结果 配置脚本 举例:配置三层子接口实现不同VLAN间的互通 组网需求 操作步骤 检查配置结果 配置

    2024年02月11日
    浏览(39)
  • 网络安全应急响应典型案例-(DDOS类、僵尸网络类、数据泄露类)

        DDOS攻击,即分布式拒绝服务攻击,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。CC攻击使用代理服务器向受害服务器发送大量貌似合法的请求(通常为HTTP GET),通常会导致网站出现了无法进行操作的情况,不仅仅影

    2024年02月10日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包