3.volatile基本原理及缺陷

目录

  • 概述
  • 案例
    • 代码如下
    • 执行结果
  • 原理
    • 实现内存可见性的过程
    • 硬件上的内存屏障
    • 底层分析
      • java中的四种内存屏障
  • 缺陷
    • 代码
    • 执行结果
  • 结束

概述

想要多线程程序正确的执行,必须要保证原子性可见性有序性。只要有一个没有被保证,就有可能导致程序运行不正确。

案例

代码如下

package com.fun.demo;public class DemoTicketVolatile {public static void main(String[] args) {TicketTask task = new TicketTask();new Thread(task, "窗口1").start();task.flag = false;System.out.println(task.flag);}static class TicketTask implements Runnable {public volatile boolean flag = true;@Overridepublic void run() {System.out.println("了线程执行");while (flag) {}System.out.println("了线程结束");}}
}

执行结果

在这里插入图片描述

原理

java语言对 volatile 的定义:java允许线程访问共享变量,为了确保共享变量被准确和一致的更新,线程应保证通过排他锁单独获得这个变量,即 volatile 可以保证多线程场景下变量的 可见性有序性。如果某变量用 volatile 修饰,则可以确保所有线程看到变量的值是一致的。

注意:volatiile 使用起来简单,但用好并不容易,对变量的操作一般会选择 JUC 中原子类,boolean 是它的一种常见用法。

实现内存可见性的过程

volatile 实现内存可见性的过程:

  • 线程写 volatile 变量的过程:
    • 1.改变线程本地内存中 volatile 变量副本的值
    • 2.将改变后副本的值从本地内存刷新至主内存
  • 线程读 volatile 变量的过程:
    • 1.从主内存中读取 volatile 变量的最新值至线程的本地内存中
    • 2.从本地内存中读取 volatile 变量的副本

硬件上的内存屏障

Load屏障,在x86上是 ifence 指令,在其它指令前插入 ifence 指令,可以让cpu寄存器中的数据失效,强制当前线程从主内存里面加载数据到cpu寄存器中

Store屏障,在x86上是 sfence 指令,在其它指令后插入 sfence 指令,能让当前线程写入cpu寄存器的最新数据 ,写入到主内存,并让其它线程可见

底层分析

volatile 实现内存可见性原理:内存屏障 (Memory Barrier)

内存屏障是一种cpu指令(系统层面的操作),用于控制特定条件下的重排序和内存可见性问题。
java编译器也会根据内存屏障的规则禁止重排序。

  • 写操作时,通过在写操作指令后加入一条store屏障指令,让本地内存中变量的值能够刷新到主内存中
  • 读操作时,通过在读操作前加入一条load屏障指令,及时读取到变量在主内存的值

java中的四种内存屏障

屏障例子详解
LoadLoad屏障Load1;LoadLoad;Load2LoadLoad中两个Load,前一个对应Load1,后一个对应Load2;保证Load1从主内存里读取过程完成,在Load2及后续读操作之前。
StoreStore屏障Store1;StoreStore;Store2StoreStore中两个Store,前一个对应Store1存储代码,后个对应Store2存储代码,在Store2及后续写操作执行前,保证Store1的写入操作已将数据写入到主内存里,确认Store1的写入操作对其它线程可见。
LoadStore屏障Load1;LoadStore;Store2LoadStore中的Load对应Load1加载代码,Store对应Store2存储代码,在Store2及后结代码写入操作执行前,保证Load1从主内存里读取完毕所需要的数据。
StoreLoad屏障Store1;StoreLoad;Load2在Load2及后续读取操作之前,保证Store1的写入操作已经将数据写入到主内存里,确认Store1的写入操作对其它处理器可见。

缺陷

代码

package com.fun.demo;public class DemoTicketVolatile {public static void main(String[] args) {TicketTask task = new TicketTask();new Thread(task, "窗口1").start();new Thread(task, "窗口2").start();new Thread(task, "窗口3").start();}static class TicketTask implements Runnable {private volatile int tickets = 100;@Overridepublic void run() {while (true) {if (tickets > 0) {try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "-正在卖票:" + tickets--);}}}}
}

执行结果

由下图可知,tickets-- 不是原子性操作。导致执行出了问题。
在这里插入图片描述

结束

至此,volatile基本原理及缺陷 就结束了,如有疑问,欢迎评论区留言。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像分类原理

一、什么是图像分类(Image Classification) 图像分类任务是计算机视觉中的核心任务,其目标是根据图像信息中所反映的不同特征,把不同类别的图像区分开来。 二、图像分类任务的特点 对于人来说,完成上述的图像分类任务简直轻而易举&#xf…

TypeScript快速入门

基础类型 类型定义例子布尔值Boolean赋值为true或者falselet isDone:boolean false数字number支持十进制、八进制、十六进制let decLiteral: number 2023; let binaryLiteral: number 0b11111100111;let octalLiteral: number 0o3747;let hexLiteral: number 0x7e7;字符串…

办公技巧:Word中插入图片、形状、文本框排版技巧

目录 一、插入图片排版技巧 二、添加形状排版技巧 三、插入“文本框”排版技巧 我们平常在制作word时候经常会遇到插入选项卡下的图片、形状和文本框这三种情况下,那么如何使得Word文档当中添加这三个元素的同时,又能保证样式美观呢,今天小…

NX二次开发UF_CAM_set_clear_plane_data 函数介绍

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_set_clear_plane_data Defined in: uf_cam_planes.h int UF_CAM_set_clear_plane_data(tag_t object_tag, double origin [ 3 ] , double normal [ 3 ] ) overview 概述 De…

【LeetCode】每日一题 2023_11_23 HTML 实体解析器(调库/打工)

文章目录 刷题前唠嗑题目:HTML 实体解析器题目描述代码与解题思路 结语 刷题前唠嗑 题目:HTML 实体解析器 题目链接:1410. HTML 实体解析器 题目描述 代码与解题思路 func entityParser(s string) (ans string) {return strings.NewRepla…

TransFusionNet:JetsonTX2下肝肿瘤和血管分割的语义和空间特征融合框架

TransFusionNet: Semantic and Spatial Features Fusion Framework for Liver Tumor and Vessel Segmentation Under JetsonTX2 TransFusionNet:JetsonTX2下肝肿瘤和血管分割的语义和空间特征融合框架背景贡献实验方法Transformer-Based Semantic Feature Extractio…

介绍几种Go语言开发的IDE

文章目录 1.前言2.几种ide2.1 Goland2.2 VsCode示例 2.3 LiteIDE2.4 Eclipse插件GoClipse2.5 Atom2.6 Vim2.7 Sublime Text 3.总结写在最后 1.前言 Go语言作为一种新兴的编程语言,近年来受到了越来越多的关注。 它以其简洁、高效和并发性能而闻名,被广…

微服务 Spring Cloud 9,RPC框架,客户端和服务端如何建立网络连接?

目录 一、客户端和服务端如何建立网络连接?1、HTTP通信2、Socket通信 二、服务端如何处理请求?1、通常来说,有三种处理方式:2、不同的处理方式对应着不同的业务场景: 三、HTTP协议传输流程四、数据该如何序列化和反序列…

【深度学习】参数优化和训练技巧

寻找合适的学习率(learning rate) 学习率是一个非常非常重要的超参数,这个参数呢,面对不同规模、不同batch-size、不同优化方式、不同数据集,其最合适的值都是不确定的,我们无法光凭经验来准确地确定lr的值,我们唯一可…

第95步 深度学习图像目标检测:Faster R-CNN建模

基于WIN10的64位系统演示 一、写在前面 本期开始,我们学习深度学习图像目标检测系列。 深度学习图像目标检测是计算机视觉领域的一个重要子领域,它的核心目标是利用深度学习模型来识别并定位图像中的特定目标。这些目标可以是物体、人、动物或其他可识…

【黑马甄选离线数仓day01_项目介绍与环境准备】

1. 行业背景 1.1 电商发展历史 电商1.0: 初创阶段20世纪90年代,电商行业刚刚兴起,主要以B2C模式为主,如亚马逊、eBay等 ​ 电商2.0: 发展阶段21世纪初,电商行业进入了快速发展阶段,出现了淘宝、京东等大型电商平台&a…

LangChain 7 文本模型TextLangChain和聊天模型ChatLangChain

LangChain系列文章 LangChain 实现给动物取名字,LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索I…