voliate实战:voliate可见性验证有序性非原子性验证

news2024/11/16 13:50:46

一、可见性验证

下面的程序验证了voliate的可见性。

public class VolatileVisibilityTest {

    private static volatile boolean inintFlag = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            System.out.println("waiting data...");
            while (!inintFlag){

            }
            System.out.println("===============success");
        }).start();

        Thread.sleep(2000);

        new Thread(() -> prepareData()).start();
    }

    public static void prepareData(){
        System.out.println("prepare data.....");
        inintFlag = true;
        System.out.println("prepare data end....");
    }
}

代码执行过程如下:
在这里插入图片描述

在这里插入图片描述

  • voliate可见性的底层实现原理
    通过程序执行的汇编指令发现,是通过锁机制实现的。

验证过程

  • 下载反汇编程序插件
    下载地址:https://download.csdn.net/download/luckywuxn/88347740
  • 插件配置
    将hsdis-amd64.dll放在 $JAVA_HOME/jre/bin/server 目录下
  • idea中设置启动参数
    -server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*VolitaleDemo.main
  • 启动程序查看结果
    控制台搜索lock关键字,将看到如下结果,结果现在lock指令执行的程序是在源代码的第28行。
    在这里插入图片描述

二、有序性

  • 示例一
public class VolatileSerialTest {

    static int x = 0,y = 0;
    static int a = 0,b = 0;

    public static void main(String[] args) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        for (int i = 0;; i ++){
            x = 0;
            y = 0;
            a = 0;
            b = 0;
            Thread one = new Thread(() -> {
                a = y;
                x = 1;
            });
            Thread other = new Thread(() -> {
                b = x;
                y = 1;
            });
            one.start();
            other.start();
            one.join();
            other.join();
            if (a == 1 && b == 1){
                long endTime = System.currentTimeMillis();
                System.out.println("经过" + (endTime - startTime) + "ms," + i + "次之后a=b=1");
                break;
            }
            System.out.println("当前执行" + i + "次");
        }
    }
}

运行上面代码,得到以下结果,由此我们可以得到结论,在没有使用voliate关键字时,两个线程中的两条指令是可以重排序的。
在这里插入图片描述

  • 示例二
public class VolatileSerialTest2 {
    private static VolatileSerialTest2 instance = null;

    private VolatileSerialTest2(){
    }

    public static VolatileSerialTest2 getInstance(){
        if (instance == null){
            synchronized (VolatileSerialTest2.class){
                if (instance == null){
                    instance = new VolatileSerialTest2();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        VolatileSerialTest2 instance = VolatileSerialTest2.getInstance();
    }

}

编译之后,通过idea插件jclasslib插件可以看到字节码文件如下
在这里插入图片描述
由JMM规范可知,如果第11、12行是最新as-if-serial & happens-before 原则的,所有这两条指令是可能重排序的,为了防止重排序,我们只需要加上voliate关键字就可以了。

三、原子性验证

下面是一个原子性验证的代码:

class Counter {
    private volatile int count = 0;
    public void increment() {
        count++;
    }
    public int getCount() {
        return count;
    }
}

public class VolatileAtomicTest {

    public static void main(String[] args) {
        final Counter counter = new Counter();
        // 创建两个线程,同时递增计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });
        thread1.start();
        thread2.start();
        // 等待两个线程执行完成
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 输出最终的计数器值
        System.out.println("Final Count: " + counter.getCount());
    }
}

运行上面代码,结果如下
在这里插入图片描述
上面程序使用两个线程同时对voliate修饰的变量count进行累计操作,voliate对所有线程都是可见的,那为什么结果不是2000呢,这是由于voliate修饰的变量并不是原子的。

最后,给大家展示一下voliate的五层实现。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1018989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot-mybatis创建项目报错day01

problem01 出现springboot引入mbatis-plus依赖单元测试时出现 Error:(3, 44) java: 程序包com.baomidou.mybatisplus.core.mapper不存在。 Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException:异常。 solution 点击右边侧栏Maven的Ge…

在visual studio里安装Python并创建python工程

在2009年&#xff0c;云计算开始发力&#xff0c;Python、R、Go这些天然处理批量计算的语言也迅猛发展。微软在2010年&#xff0c;把Python当成一个语言包插件&#xff0c;集成到了visual studio 2010里。在"云优先&#xff0c;移动优先"的战略下&#xff0c;于2015年…

直方图规定化,计算 SML 映射(数字图像处理大题复习 P3)

文章目录 1. 累计直方图概率2. 累计规定直方图3. 根据累计直方图概率和累计规定直方图 计算 SML 映射4. 计算变化后直方图结果 1. 累计直方图概率 我们最终的目的是从 表 1 变成 表 2 首先我们仍要先求出累计直方图概率 2. 累计规定直方图 把规定直方图抄到下面 然后我们…

Python入门教学——self

1、简介 我们知道在创建类的实例方法时&#xff0c;需要传入一个self&#xff0c;不然就会报错。那么这个self是什么呢&#xff1f;有什么作用呢&#xff1f; def 方法名(self,args): # args为参数pass 在Python类中规定&#xff0c;函数的第一个参数是实例对象本身&#xff…

FreeRTOS进阶-任务管理实践

一、使用接口函数创建任务 1.动态创建 xTaskCreate() 函数原型&#xff1a; BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数 const char * const pcName, // 任务的名字 const configSTACK_DEPTH_T…

渗透测试之漏洞挖掘指南(一)

1.漏洞挖掘中什么漏洞最多&#xff1f; 新手想快速挖掘到漏洞&#xff0c;要专注在业务逻辑与前端漏洞 -- 业务逻辑 &#xff08;弱密码&#xff0c;等等&#xff09; -- 前端漏洞 &#xff08;xss, csrf , cors, jsonp...&#xff09; 2. 常见漏洞提交平台 注册应急响应中…

投资理财基础知识:指数基金定投是什么?

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家分享一下投资理财基础知识&#xff1a;指数基金定投是什么&#xff1f; 首先&#xff0c;你需要进行理财风险偏好测试&#xff0c;以确定自己的类型。风险偏好一般分为保守型、稳健型、平衡型、进取型和激进型。每个人对风…

C# 实现迷宫游戏

智能提示&#xff1a; /// <summary>/// 迷宫/// </summary>internal class Maze : IDisposable{private MazeCell[,] cells;private readonly Stack<MazeCell> stack new Stack<MazeCell>();private readonly Random rand new Random();private int…

Python 文件写入操作

视频版教程 Python3零基础7天入门实战视频教程 w模式是写入&#xff0c;通过write方法写入内容。 # 打开文件 模式w写入&#xff0c;文件不存在&#xff0c;则自动创建 f open("D:/测试3.txt", "w", encoding"UTF-8")# write写入操作 内容写入…

电脑软件:火绒应用商店功能体验(附下载)

火绒作为国内杀毒软件的一股清流&#xff0c;相信很多电脑爱好者都使用火绒软件作为自己的电脑杀毒软件&#xff0c;火绒杀毒软件的最大特点是软件没有弹窗广告、电脑杀毒可靠、完全免费使用、支持拦截烦人的弹窗广告。今天主要给大家介绍火绒官方内测了一款电脑应用商店独立软…

RK3588平台开发系列讲解(安卓篇)Android12 获取 root 权限

文章目录 一、关闭 selinux二、注释用户组权限检测三、su 文件默认授予 root 权限沉淀、分享、成长,让自己和他人都能有所收获!😄 📢获取Android设备的root权限是指取得超级用户(root用户)的权限,使得用户可以对系统进行更广泛的修改和操作。但需要注意,获取root权限…

VMware Workstation Pro各版本下载安装教程

VMware Workstation Pro下载 打开浏览器&#xff0c;输入VMware Workstation Pro 找到VMware Workstation Pro官网并点击进入&#xff0c;官网地址&#xff1a;https://www.vmware.com/cn/products/workstation-pro.html 进入官网首页后可以下载最新版本的VMware Workstation P…

【JAVA-Day21】序列化和反序列化,学会Java的编解码方法

标题序列化和反序列化&#xff0c;学会Java的编解码方法 序列化和反序列化&#xff0c;学会Java的编解码方法摘要引言一、什么是序列化1.1 序列化的过程 二、什么是反序列化2.1 反序列化的过程 三、为什么要进行序列化和反序列化3.1 主要目的3.2 应用场景 四、总结参考资料 博主…

linux-gic中断分析

linux-gic中断分析 这里主要分析 linux kernel 中 GICv3 中断控制器的代码(drivers/irqchip/irq-gic-v3.c)。 一、设备树 先来看下中断控制器的设备树信息&#xff1a; gic: interrupt-controller3400000 {compatible "arm,gic-v3";#interrupt-cells <3>;…

【pytest】conftest.py使用

1. 创建test_project 目录 test_project/sub/test_sub.py def test_baidu(test_url):print(fsub {test_url}) test_project/conftest.py 设置钩子函数 只对当前目录 和子目录起作用 import pytest #设置测试钩子函数 pytest.fixture() def test_url():return "http…

性能测试-性能测试的标准依据和价值(1)

性能测试的依据 国际标准化组织ISO/IEC JTC1/SC7/WG6开展了软件质量度量和评价的标准化工作&#xff0c;制定了ISO/IEC 25000 SQuaRE系列国际标准。 GB/T 25000.1—2021《系统与软件工程 系统与软件质量要求和评价(SQuaRE)第1部分&#xff1a;SQuaRE指南》便是采纳ISO/IEC 25…

巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器的相同和不同之处

巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器的相同和不同之处 1、概述 用 MATLAB 中的函数可以设计巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器&#xff0c;我们用MATLAB的函数&#xff0c;在相同的条件下观察巴特沃斯、切比雪夫I型、 切比雪夫Ⅱ型和椭圆型滤…

如何看待近期tiktok大批量封号问题?

近期大量客户反馈Tiktok账号大批量被封&#xff0c;了解这类客户的情况后&#xff0c;得知被封的账号大部分都是为搬运国内视频上传的账号类型&#xff0c;从这次的事件可以看出&#xff0c;tk对视频的检测以及内容要求度越来越高&#xff0c;Tk风控升级&#xff0c;回导致很多…

【Nacos】Nacos服务注册源码分析(二)

在上篇文章中&#xff0c;我们主要聚焦于Nacos服务注册在服务端grpc设计层面的一些代码。本篇文章将深入探讨服务注册的相关逻辑&#xff0c;通过细致的分析来更全面地理解这一过程。 NamingGrpcClientProxy.registerService 我们从NamingGrpcClientProxy的registerService方法…

Vue项目中使用element-plus的el-table组件-组件使用-样式修改

项目配置 <div class"table-wrap"><el-tableclass"table-card-container":data"tableData"style"width: 100%"><template v-for"column in tableColumn"><el-table-columnv-if"column.isShow&qu…