java 并发——volatile
java 并发——volatile
介绍
维基百科: volatile 是一个类型修饰符(type specifier).volatile 的作用是确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
看了上面的话感觉不是那么的好理解,因为 volatile 关键字是和 java 内存模型 JMM(java memory model)是息息相关的,所以在介绍 volatile 之前我们先来看一下 java 内存模型.
内存模型概念
我们的程序执行指令是从 cpu 中执行的,程序执行肯定和数据脱不开干系,这些数据肯定都是在计算机的物理内存中进行.但是随着 cpu 越来越牛x,而内存的话就会显得相对来说不那么效率,这就导致每次 cpu 执行导致每次操作数据都要去内存操作,这样就很耗费时间.
由于计算机的存储设备与 cpu 的运算速度有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样处理器就无须等待缓慢的内存读写了。
解决了效率的问题但是随之而来也就出现了新的问题需要解决——缓存一致性.因为在程序运行期间会将运行所需要的数据从内存中复制一份到 cpu 高速缓存中之后再进行对应的运算,再运算期间数据的读取是从高速缓存直接读取并不会再取读取内存中的数据了,只有再运算结果出来后才会将数据重新刷新会到内存中.
解决方法:
- 通过数据总线加锁的方式 LOCK.(但是这样效率极为低下不建议)
- 缓存一致性协议.(确保每个缓存中使用的共享变量的副本是一致的。其核心思想如下:当某个 cpu 在写数据时,如果发现操作的变量是共享变量,则会通知其他 cpu 告知该变量的缓存行是无效的,因此其他 cpu 在读取该变量时,发现其无效会重新从主存中加载数据。)

java 内存模型
java 内存模型规定了所有的变量都存储在主内存中,每条运行的线程还是各自的工作内存区域,线程运行的是会从主内存中将变量从主内存拷贝一份到自己的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不是直接操作主内存,不同的线程之间工作内线是不会共享的。直到线程运算结束将值刷新到主内存后,其他线程才可见(可见性).

先举一个场景
public class Test {
static int i = 1;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
i++;
});
Thread t2 = new Thread(() -> {
i++;
});
t1.start();
t2.start();
System.out.println(Test.i);
}
}
这个场景输出有可能不是 3,两个线程从主存中读取 i 的值(1)到各自的高速缓存中,然后线程 t1 执行 +1 操作并将结果写入高速缓存中,最后写入主存中,此时主存 i==2,线程 t2 做同样的操作,但是线程 t2 的工作内存 i 的值有可能还是 1但是现在主存中的 i 应该是 2。所以 t2 执行完最终结果为 2 再将 2 刷新入主内存中而并不是 3。这种现象就是缓存一致性问题。
我们在并发编程中都会知道这几个概念:
- 原子性: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行.
- 可见性: 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值.
- 有序性: 即程序执行的顺序按照代码的先后顺序执行.多线程环境下有影响.
volatile
我们在回顾一下一开始介绍 volatile 的话: volatile 是一个类型修饰符(type specifier).volatile 的作用是确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
看了上面的话只表达出了一点: 可见性.其实还有一个作用就是禁止指令重排序(重排序后面会单独说).所以使用 volatile 关键字来修饰变量就不会存在缓存一致性的问题了.现在我们简单说下 volatile 是怎么禁止指令重排序的: 加入 volatile关键字和没有加入 volatile 关键字时所生成的汇编代码发现,加入 volatile 关键字时,会多出一个 lock 前缀指令。lock 前缀指令其实就相当于一个内存屏障。内存屏障是一组处理指令,用来实现对内存操作的顺序限制。
volatile 就暂且到这里了,感兴趣的朋友可以继续深入研究.volatile 相对于 synchronized 稍微轻量些,在某些场合它可以替代 synchronized,但是又不能完全取代 synchronized.感谢观看!
java 并发——volatile的更多相关文章
- Java并发-volatile的原理及用法
Java并发-volatile的原理及用法 volatile属性:可见性.保证有序性.不保证原子性.一.volatile可见性 在Java的内存中所有的变量都存在主内存中,每个线程有单独CPU缓存内存 ...
- Java并发——volatile的原理
111 Java并发——volatile的原理
- Java 并发 —— volatile 关键字
volatile 修饰变量等于向编译器传达如下两层含义: 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的. 禁止进行指令重排序. volat ...
- JAVA并发--volatile
学过计算机组成原理的一定知道,为了解决内存速度跟不上CPU速度这个问题,在CPU的设计中加入了缓存机制,缓存的速度介于CPU和主存之间.在进行运算的时候,CPU将需要的数据映射一份在缓存中,然后直接操 ...
- Java并发--volatile关键字
一.volatile的实现原理 synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁,而volatile就可以说是JVM提供的最轻量级的同步机制.JMM告诉我们,各个线程会将共 ...
- Java并发--volatile详情
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- Java并发——volatile关键字
什么是内存可见性? 这里就要提一下JMM(Java内存模型).当线程在运行的时候,并不是直接直接修改电脑主内存中的变量的值.线程间通讯也不是直接把一个线程的变量的值传给另一个线程,让其刷新变量.下面是 ...
- Java并发——volatile关键字的使用
volatile关键字的使用volatile关键字原理适合使用volatile关键字的情况当且仅当满足以下所有条件时,才==应该==使用volatile关键字:volatile关键字的作用volati ...
- Java并发——volatile
CPU的内存模型如下:
随机推荐
- python学习笔记之入门
1.变量 变量即为可以改变的量,值是可以更改的. 如何定义 name = ‘name’ age = 20 .......... 变量的定义规范 1.变量名只能是 字母.数字或下划线的任意组合 .2. ...
- gitlab fatal: Authentication failed for 'http://10.2.80.17:8090/yeyichao/201904041026PROj.git/'
fatal: Authentication failed for 'http://10.2.80.17:8090/yeyichao/201904041026PROj.git/' git config ...
- fiddler 暂停抓包
或者点击左下角 capturing
- pixi与lottie-web的benchmark测试
生产版本 "dependencies": { "lottie-web": "^5.5.7", "pixi-spin ...
- Java开发中的23种设计模式详解(1)创建型
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- top查看进程的参数
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不 ...
- Tensorflow读取大数据集的方法,tf.train.string_input_producer()和tf.train.slice_input_producer()
1. https://blog.csdn.net/qq_41427568/article/details/85801579
- Codeforces 1178F DP
题意:有一张白纸条,你需要给这张纸条染色.染色从颜色1开始染色,每次选择纸条的一段染色时,这一段的颜色必须是相同的.现在给你染色后的纸条,问有多少种染色方案? F1: 思路:最开始的想法是以染色顺序为 ...
- Failed to resolve com.android.support:support-compat:25.4.0
3down votefavorite I am trying to include this library to my project by adding compile 'jp.wasabee ...
- springboot 2.x相关配置
1.在配置文件中进行配置 #############指定项目中所有的日期类型返回json格式########### spring.jackson.date-format=yyyy-MM-dd HH:m ...