volatile

浅尝java内存模型(JMM)

大憨熊 提交于 2020-01-12 00:18:02
本文参考《深入理解虚拟机》一书 一.JMM中的主内存和工作内存 主内存:主要是存储线程要读取的数据,如实例字段、静态字段和数组元素,局部变量和形参不存储在主存。 工作内存:每一个线程都有自己的工作内存,工作内存存储从主存中copy的一份副本,线程只能操作工作内存中的数据,不能直接操作主存中的数据。不同线程之间也无法访问其它线程的工作内存变量线程间变量值传递需要通过主存来进。 内存间进行交互操作: 由上面的交互关系可知,关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步到主内存之间的实现细节,Java内存模型定义了以下八种操作来完成: lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。 unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。 read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用 load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。 use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。 assign(赋值):作用于工作内存的变量

Java面试官最爱的volatile关键字

别等时光非礼了梦想. 提交于 2020-01-11 14:27:02
在Java相关的岗位面试中,很多面试官都喜欢考察面试者对Java并发的了解程度,而以 volatile 关键字作为一个小的切入点,往往可以一问到底,把Java内存模型(JMM),Java并发编程的一些特性都牵扯出来,深入地话还可以考察JVM底层实现以及操作系统的相关知识。 下面我们以一次假想的面试过程,来深入了解下volitile关键字吧! 面试官: Java并发这块了解的怎么样?说说你对volatile关键字的理解 就我理解的而言,被volatile修饰的共享变量,就具有了以下两点特性: 保证了不同线程对该变量操作的内存可见性 禁止指令重排序 面试官: 能不能详细说下什么是内存可见性,什么又是重排序呢? 这个聊起来可就多了,我还是从Java内存模型说起吧。 Java虚拟机规范试图定义一种Java内存模型(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让Java程序在各种平台上都能达到一致的内存访问效果。简单来说,由于CPU执行指令的速度是很快的,但是内存访问的速度就慢了很多,相差的不是一个数量级,所以搞处理器的那群大佬们又在CPU里加了好几层高速缓存。 在Java内存模型里,对上述的优化又进行了一波抽象。JMM规定所有变量都是存在主存中的,类似于上面提到的普通内存,每个线程又包含自己的工作内存,方便理解就可以看成CPU上的寄存器或者高速缓存。所以线程的操作都是以工作内存为主

STM32 volatile关键字

£可爱£侵袭症+ 提交于 2020-01-11 10:05:55
为了提供对特殊地址的稳定访问。 [C] 纯文本查看 复制代码 ? 1 2 3 int i=10; int j=i; //1 int k=i; //2 此时编译器对上面代码进行优化,因为在1、2语句中,i 没有被用作左值(没有被赋值)。这时候编译器认为i 的值没有发生改变,所以在1语句时从内存取出 i 的值赋给 j 之后,这个值没有被丢掉,而是在2语句中继续用这个值赋值给k。编译器不会生成汇编代码重新从内存里取 i ,这样提高了效率 [C] 纯文本查看 复制代码 ? 1 2 3 volatile int i=10; int j=i; int k=i; volatile 关键字告诉编译器,i 是随时可能发生变化的,每次使用它的时候必须从内存取出 i 的值,因而编译器生成的汇编代码会重新从 i 的地址处读取数据放在k中。 来源: https://www.cnblogs.com/ransn/p/8483155.html

C中的volatile用法

梦想的初衷 提交于 2020-01-11 07:57:52
C中的volatile用法 volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2)

C++ volatile关键字

好久不见. 提交于 2020-01-11 05:00:19
  volatile和const关键字一样,是一个类型修饰符,表示变量可以被编译器的某些未知因素修改,比如操作系统,硬件,某些线程等。遇到这个关键字声明的变量,编译器访问该变量的代码将不再进行优化,以提供对特殊地址的稳定访问。   有代码如下:   int i = 10; int j = i;//语句1 int k = i;//语句2 这时候编译器进行代码优化,因为在语句1和语句2中,i不作为左值,编译器认为i的值没有发生变化,所以在语句1中将i的值取出赋给j之后i的值并未丢弃,而是在语句2中继续赋给k编译器不会产生汇编代码重新从i里面取值,这样做提高了效率,但是要注意,语句i要没有用作左值才行。而且编译器只在release模式下才对内存进行优化,在debug模式下volatile不会对内存进行优化。   有代码如下: int i = 1; int j = i; int k = i; volatile int a = 10; volatile int b = a; volatile int c = a; debug模式下的汇编代码: int i = 1; 010D17BE mov dword ptr [i],1 int j = i; 010D17C5 mov eax,dword ptr [i] 010D17C8 mov dword ptr [j],eax int k = i;

Visual C++ Volatile

杀马特。学长 韩版系。学妹 提交于 2020-01-11 04:52:10
问题 The MSDN docs for "volatile" in Visual C++ indicate that writes have "release semantics" and that reads have "acquire semantics", in addition to ensuring that reads always read from memory and that writes always write accordingly. The C spec for "volatile" includes the second part (don't do crazy optimizations), but not the first part (a memory fence). Is there any way in Visual C++ to get the "C" volatile behaviour only, without the memory fence? I want to force a variable to always be on

C中的volatile用法

為{幸葍}努か 提交于 2020-01-11 03:24:14
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2) 一个中断服务子程序中会访问到的非自动变量(Non

附2 volatile

馋奶兔 提交于 2020-01-11 01:43:35
注:在看这篇文章之前,如果对ArrayList底层不清楚的话,建议先去看看 ArrayList 源码解析。 http://www.cnblogs.com/java-zhao/p/5102342.html 1、对于CopyOnWriteArrayList需要掌握以下几点 创建:CopyOnWriteArrayList() 添加元素:即add(E)方法 获取单个对象:即get(int)方法 删除对象:即remove(E)方法 遍历所有对象:即iterator(),在实际中更常用的是增强型的for循环去做遍历 注:CopyOnWriteArrayList是一个线程安全,读操作时无锁的ArrayList。 2、创建 public CopyOnWriteArrayList() 使用方法: List<String> list = new CopyOnWriteArrayList<String>(); 相关源代码: private volatile transient Object[] array;//底层数据结构 /** * 获取array */ final Object[] getArray() { return array; } /** * 设置Object[] */ final void setArray(Object[] a) { array = a; } /** *

Guava限流器RateLimiter中mutexDoNotUseDirectly/锁的使用

倾然丶 夕夏残阳落幕 提交于 2020-01-10 22:04:27
文章目录 源码 疑惑 解惑 写在最后 源码 在阅读Guava限流器代码相关实现时,很多操作都需要加锁,比如在setRate方法中: public final void setRate ( double permitsPerSecond ) { checkArgument ( permitsPerSecond > 0.0 && ! Double . isNaN ( permitsPerSecond ) , "rate must be positive" ) ; synchronized ( mutex ( ) ) { doSetRate ( permitsPerSecond , stopwatch . readMicros ( ) ) ; } } 上述代码的重点即是 synchronized (mutex()){} ,用来在真正的修改速率(doSetRate)方法前加锁,避免出现并发问题。 接下来看 mutex() 方法: // Can't be initialized in the constructor because mocks don't call the constructor. @MonotonicNonNull private volatile Object mutexDoNotUseDirectly ; private Object mutex ( ) {

C中的volatile用法

天涯浪子 提交于 2020-01-10 18:16:57
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2) 一个中断服务子程序中会访问到的非自动变量(Non