首页 > 其他分享 >决战圣地玛丽乔亚Day14 ----Volatile关键字分析

决战圣地玛丽乔亚Day14 ----Volatile关键字分析

时间:2023-02-18 17:36:57浏览次数:35  
标签:Day14 缓存 乔亚 变量 原子 ---- 线程 先行 操作

volatile:

背景: 

CPU和主存读写速度不一致,出现了高速缓存。把一些经常读的数据存入高速缓存,交互计算和高速缓存进行,修改完毕后再从高速缓存刷回主存中。

但是问题来了! CPU是多核,不同的cpu都有自己的高速缓存,那么一份数据可能就被缓存在不同的cache中。 并发操作就会造成数据的不准。

硬件方面可以通过缓存一致性协议,Lock锁总线的方式来支持并发操作。但是太过于笨重,是很早期的产物了。然后又出现缓存一致性协议。在写数据时,

判断是否当前使用的数据时共享变量,如果是共享变量就把该变量在其他的CPU缓存中置为失效,如果其他CPU读取发现失效缓存会重新从内存读取。

 

Volatile其实是一个很基础底层的并发问题,如果想完全弄懂,首先要知道并发的三个概念:原子性、可见性、有序性。这是聊并发绕不开的三个概念。

原子性:

要么整个流程全部完成,要么就全部不做。在过程中不可打断。

可见性:

多线程操作,对数据的修改,其他线程是否知情。

有序性:

这个主要是处理器对程序进行效率优化导致,会进行指令重排序。单线程指令重排序,会保证最终的结果一致性,但是如果多线程还是进行指令重排序,就会影响最终结果的一致性。

 

java对于并发三要素的规范:
内存模型(所有变量存在于内存中,每个线程有自己的工作内存(cache))

1.原子性。

对于基础数据类型变量的读写保证原子性。

但是如 X++ 

    x = x +1

           y = x 

这种操作都不是原子性

 

2.可见性

volatile保证,修改volatile的值后会立刻更新到主存

3.有序性

sychronized和Lock保证有序性,因为变成了单线程模式。

java内存模型的happens-before原则:

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
  • volatile变量规则:对变量的写优先于读
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C。  A>B   B>C   A>C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

理解一下就是单线程下,会保证最终结果一致性。变量的写在读之前,变量的解锁在锁之前,变量的顺序有传递性

 

 深入剖析Volatile关键字:

1.保证不同线程的实时可见性!修改完立马刷新数据,其他线程共享的置为失效。

2.禁止指令重排序!

1、原子性

Volatile也只能保证读/写的原子性,对于x++这种,需要先读后写的非一步操作,是不能保证原子性的。

原因:因为修改后立即刷新到内存,其他缓存失效这个操作,是一步到位的。如果是读+写这种非一步操作,完全可以在线程1读后阻塞,然后线程2读,两个线程读到的数据是一致的,

但是两个线程分别+1是在读到的数据上进行修改,读到的数据已经是老数据了,会造成误差。

对于这种情况,我们可以使用sychronized和Lock或者AtomicInteger这种封装好包进行原子性操作。

AtomicInteger主要是用到了CAS操作,CAS说白了就是用处理器提供的CMPXCHG指令实现了原子操作

3、有序性

标签:Day14,缓存,乔亚,变量,原子,----,线程,先行,操作
From: https://www.cnblogs.com/dwj-ngu/p/17130745.html

相关文章

  • 加速alist打开速度
    自定义头部,使用阿里的CDN<scriptsrc="https://polyfill.alicdn.com/polyfill.min.js?features=String.prototype.replaceAll"></script>使用七牛云的免费CDN存放l......
  • Istio和Envoy在服务网格中的架构
    分两部分来分析,首先是Istio组件Pilot与Envoy的交互过程。1)Pilot使用client-go的Informer组件连接APIServer获取集群中所有服务的Service和对应的Endpoints信息,这样就完......
  • 1.Linux系统安装
    0.操作系统版本[root@yuanzj~]#cat/etc/redhat-releaseCentOSrelease6.10注意:在安装Oracle10g版本数据库时候,需要修改版本号为[root@yuanzj~]#cat/etc/redhat-......
  • C# List集合查找删除指定数据
    1.实体类publicclassFaultLevelModel{publicstringLBWJ{get;set;}publicstringLBSJ{get;set;}publicstringINDCODE{get;set;}}2.操作第......
  • 【算法训练营day48】LeetCode198. 打家劫舍 LeetCode213. 打家劫舍II LeetCode337. 打
    LeetCode198.打家劫舍题目链接:198.打家劫舍独上高楼,望尽天涯路dp[i]表示的是偷窃0-i房屋所能获得的最大金额。classSolution{public:introb(vector<int>&n......
  • Arduino esp8266 error DEBUG_ESP_PORT was not declared in this scope
    error:'DEBUG_ESP_PORT'wasnotdeclaredinthis scope解决方法:菜单,工具,Debugport:,Serial 解决!From:https://blog.csdn.net/brook0344/article/details/1061693......
  • Linux远程连接
    一、Linux远程链接1、前置步骤(1)确定Linux服务器的IP地址,可以通过ifconfig查看对应的IP地址(2)实际工作中,IP地址是由服务器管理人员给我们2、确......
  • 你好
    emmmm#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<vector>#include<cstring>#include<unordered_set>#include<set......
  • java中取模的本质,即%的运算结果
    Java中%的本质如下公式:m%n=m-(int)(m/n)*n且看例题已知a=2,b=3,则表达式a%b*4%b的值为(2)运用公式得知:a%b=2%3=2-(0)3=2其中2/3=0.666666,取整数为04......
  • Redis实战11-实现优惠券秒杀下单
    本篇,咱们来实现优惠券秒杀下单功能。通过本篇学习,我们将会有如下收获:1:优惠券领券业务逻辑;2:分析在高并发情况下,出现超卖问题产生的原因;3:解决超卖问题两种方案:版本号法及C......