volatile能保证原子性吗?为什么?

news2024/11/24 23:08:06

一、问题解析

volatile通常被比喻成”轻量级的synchronized“,也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是一个变量修饰符,只能用来修饰变量。无法修饰方法及代码块等。

volatile的用法比较简单,只需要在声明一个可能被多线程同时访问的变量时,使用volatile修饰就可以了。

但是, volatile在线程安全方面,可以保证有序性和可见性,但是是不能保证原子性的 。

synchronized可以保证原子性 ,因为被synchronized修饰的代码片段,在进入之前加了锁,只要他没执行完,其他线程是无法获得锁执行这段代码片段的,就可以保证他内部的代码可以全部被执行。进而保证原子性。

那么,为什么volatile不能保证原子性呢?因为他不是锁,他没做任何可以保证原子性的处理。当然就不能保证原子性了。
比如有如下代码:

 


public class Test {

    volatile int number = 0;

    public void increase() {
        number++;
    }

    public static void main(String[] args) {
        Test volatileAtomDemo = new Test();
        for (int j = 0; j < 10; j++) {
            new Thread(() -> {
                for (int i = 0; i < 1000; i++) {
                    volatileAtomDemo.increase();
                }
            }, String.valueOf(j)).start();
        }
        while (Thread.activeCount() > 2) {
            Thread.yield();
        }

        System.out.println(Thread.currentThread().getName() +
                           " final number result = " + volatileAtomDemo.number);
    }

}

Thread.yield()方法被用来暂停当前正在执行的线程,以允许其他线程获得执行机会,以此来提高并发竞争。 

 

以上程序,正常情况下,输出结果应该是10000,但是真正执行的话就会发现,没办法保证每次执行结果都是10000,这就是因为i++这个操作没办法保证他是原子性的。
i++被拆分成3个指令:
●执行GETFIELD拿到主内存中的原始值number。
●执行IADD进行加1操作。
●执行PUTFIELD把工作内存中的值写回主内存中。

当多个线程并发执行PUTFIELD指令的时候,会出现写回主内存覆盖问题,所以才会导致最终结果不为 10000,所以 volatile 不能保证原子性。

二、粉丝福利

我是浮生,一个工作十四年经验的Java程序员!

最近很多同学问我有没有java学习资料,我根据我从小白到架构师多年的学习经验整理出来了一份80W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴 可以关注我
公众号:“ 
灰灰聊架构 ”, 回复暗号:“ 321 ”即可获取

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

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

相关文章

intel三年来首次大更新竟然倒吸牙膏,线程数砍掉25%!

每年科技圈最热闹的几个话题&#xff0c;无非是几大科技公司发布新的产品&#xff0c;那这其中必然有核心巨头 intel 的身影。 据外媒 Benchlife 披露&#xff0c;英特尔计划在其 Arrow Lake-S 架构 Core Ultra 200 台式机 CPU 系列中推出共计 21 款 CPU。 这是 intel 首次在桌…

【嵌入式大赛应用赛道】机械手臂

电机 进步电机&#xff1a;它的转动是以确定的步数进行的&#xff0c;只要计算好脉冲数量和频率&#xff0c;就可以准确预测和控制电机的转动角度、速度以及停止的位置 伺服电机&#xff1a;将输入的电信号&#xff08;如电压或电流指令&#xff09;转换成轴上的精确旋转运动…

突发!超60篇被标记!Elsevier旗下顶刊,“On Hold”长达10个月!再次沦陷“新”风波!

【欧亚科睿学术】 近日&#xff0c;中科院老牌TOP期刊Chemosphere对超过60篇论文发布了关注声明&#xff0c;原因是正在调查可能存在的编辑利益冲突、作者身份异常以及同行评审和引用操纵问题。 图片来源&#xff1a;期刊官网 2024年4月11日&#xff0c;该期刊在线发布的一份…

WT99C262-SG LoRa开发板使用教程

WT99C262-SG模块是全新一代的Wi-FiBLELoRa无线扩频模块&#xff0c;基于启明云端WTLRC262-SG系列模组设计开发的新一代LoRa扩频芯片方案设计的无线串口模块。具有多种传输方式&#xff0c;LoRa扩频技术&#xff0c;且模组大部分管脚均已引出至两侧排针&#xff0c;开发人员可根…

msvcp140_codecvt_ids.dll找不到要如何处理?简单的修复方法分享

在使用Windows操作系统时&#xff0c;用户可能会遇到“无法找到msvcp140_codecvt_ids.dll”这一错误信息。该提示通常发生在启动某些应用程序时&#xff0c;提示失去了关键的动态链接库文件&#xff08;DLL&#xff09;依赖。此DLL文件属于Microsoft Visual C Redistributable软…

二进制搭建k8s

实验环境&#xff1a; k8s集群master01:192.168.1.11 k8s集群master02:192.168.1.22 master虚拟ip&#xff1a;192.168.1.100 k8s集群node01:192.168.1.33 k8s集群node01:192.168.1.44 nginxkeepalive01&#xff08;master&#xff09;:192.168.1.55 nginxkeepalive02&a…

纯血鸿蒙APP实战开发——Navigation页面跳转对象传递案例

介绍 本示例主要介绍在使用Navigation实现页面跳转时&#xff0c;如何在跳转页面得到转入页面传的类对象的方法。实现过程中使用了第三方插件class-transformer&#xff0c;传递对象经过该插件的plainToClass方法转换后可以直接调用对象的方法&#xff0c; 效果图预览 使用说…

CIBERSORTx网页版报错

解决方式&#xff1a;bulk RNA-seq不能包含NA值

大白话!大模型(LLMs)私有化的三种方式:Prompts、Embeddings、Fine-tuning

私有化大模型的三种方式 随着我们使用大模型的深入呢&#xff0c;我们会发现这样一个现象&#xff0c;我们正常情况下问大模型的问题&#xff0c;会得到一个非常普适的回答&#xff0c;就是大模型会根据自己的训练的这个过往的一些知识的积累&#xff0c;然后告诉我们他认为最…

海外盲盒系统开发,开拓全球盲盒市场

盲盒作为经久不衰的行业&#xff0c;市场发展空间不断扩大。近几年&#xff0c;盲盒出海成为了我国盲盒发展的新赛道&#xff0c;各个盲盒企业更是纷纷摩拳擦掌&#xff0c;开拓海外市场&#xff0c;我国盲盒正在全世界范围内实现多元化发展。此外&#xff0c;我国是世界上有名…

光伏行业该如何起步?

随着全球对可再生能源的需求日益增长&#xff0c;光伏行业作为其中的佼佼者&#xff0c;正迎来前所未有的发展机遇。然而&#xff0c;对于新进入者或希望在这一领域有所建树的企业来说&#xff0c;如何起步并稳健发展是一个值得深思的问题。以下是一些关于光伏行业起步的建议。…

AniPortrait详细讲解以及完整搭建流程(有问题留言)

AniPortrait是一款真实感人像动画的音频驱动合成的AI程序。 下面是它的github源码: GitHub - Zejun-Yang/AniPortrait: AniPortrait: Audio-Driven Synthesis of Photorealistic Portrait AnimationAniPortrait: Audio-Driven Synthesis of Photorealistic Portrait Animati…

[Vs2019报错找不到服务实例的解决方案]

计算机疑难杂症记录与分享004 Vs2019报错找不到服务实例的解决方案1、问题现象1.1、问题一&#xff1a;打开vs2019打开项目工程文件&#xff0c;直接弹窗报错1.2、问题二&#xff1a;能打开工程了。识别项目文件不兼容问题。 2、问题原因3、问题一的解决3.1、方法一(亲测无效)3…

Java的response返回Json格式

问题 今天开发过程中&#xff0c;写了个拦截器&#xff0c;对于所以请求进行一个token的工作&#xff0c;对于不合标准的token返回错误&#xff0c;在网上找了个拦截器进行二次开发。 package com.maizhiyu.yzt.handle;import org.springframework.beans.factory.annotation.…

Python数据分析常用模块的介绍与使用

Python数据分析模块 前言一、Numpy模块Numpy介绍Numpy的使用Numpy生成数组ndarrayarray生成数组arange生成数组random生成数组其他示例 关于randint示例1示例2 关于rand Numpy数组统计方法示例 二、Pandas模块pandas介绍Series示例 DataFrame示例 三、其他模块Matplotlib/Seabo…

通过单总线实现单片机之间的数据传输

单总线、没有时钟线的通信时&#xff0c;不能使用简单的高低电平来通信&#xff0c;因为接收方不知道此时发送的数据是第几位数据&#xff0c;容易造成错乱。 因此在使用一根线对外传输数据时&#xff0c;需要自定义一个通信协议&#xff0c;它至少要包含格式头数据&#xff0c…

什么是直接内存(NIO)

直接内存不受 JVM 内存回收管理&#xff0c;是虚拟机的系统内存&#xff0c;常见于 NIO 操作时&#xff0c;用于数据 缓冲区&#xff0c;分配回收成本较高&#xff0c;但读写性能高&#xff0c;不受 JVM 内存回收管理。 举例 当上传一个较大文件&#xff08;200M&#xff09;…

python REST 请求验证

REST 请求验证 在Python中&#xff0c;可以使用cerberus库来进行REST请求的验证。以下是一个简单的示例&#xff0c;演示如何使用cerberus进行请求数据的验证。 首先&#xff0c;安装cerberus库&#xff1a; pip install cerberus # 安装cerberus库 -- Anaconda 环境下安装 …

SQL常用函数

一、日期相关函数 1、CURDATE() / CURRENT_DATE 返回当前日期 2、CURRENT_TIME()/CURTIME() 返回当前时间 3、CURRENT_TIMESTAMP 返回当前日期时间 4、DATE()从日期或日期时间表达式中提取日期值 5、DATEDIFF(d1,d2)计算日期 d1->d2 之间相隔的天数 6、DATE_FORMAT按表达式…