我编写了一个简单的Java程序:
package com.salil.threads;
public class IncrementClass {
static volatile int j = 0;
static int i = 0;
public static void main(String args[]) {
for(int a=0;a<1000000;a++);
i++;
j++;
}
}
这将为I和j生成以下反汇编代码(删除了剩余的反汇编代码):
0x0000000002961a6c: 49ba98e8d0d507000000 mov r10,7d5d0e898h
; {oop(a 'java/lang/Class' = 'com/salil/threads/IncrementClass')}
0x0000000002961a76: 41ff4274 inc dword ptr [r10+74h]
;*if_icmpge
; - com.salil.threads.IncrementClass::main@5 (line 10)
0x0000000002961a7a: 458b5a70 mov r11d,dword ptr [r10+70h]
0x0000000002961a7e: 41ffc3 inc r11d
0x0000000002961a81: 45895a70 mov dword ptr [r10+70h],r11d
0x0000000002961a85: f083042400 lock add dword ptr [rsp],0h
;*putstatic j
; - com.salil.threads.IncrementClass::main@27 (line 14)
这就是我对以下汇编代码的理解:
JMM指出,在每次易失性读取之前必须有一个加载内存屏障,在每次易失性写入之后必须有一个存储屏障。我的问题是:
屏障可能会被你的即时编译器优化出来,因为你的程序是单线程的(只有一个线程——主线程),就像单线程环境下的锁可以被优化出来一样,这种优化是独立于处理器架构的。
Java中的< code>volatile关键字仅保证线程本地副本和缓存将被跳过,值将直接从主内存加载或写入主内存。然而,它不包含锁定机制。因此,从< code>volatile中读取数据或向< code>volatile中写入数据是原子性的,而是一系列的读取和写入操作,如上所述
j
不是原子的,因为其他一些线程可以在读取和写入主存变量之间修改< code>j的值。为了实现原子增量,你需要使用CAS操作,它被封装在java的原子类中,比如< code>AtomicInteger等。或者,如果您喜欢低级编程,您可以在< code>Unsafe类中使用原子方法,例如< code > Unsafe . compareandswapint 等。
因此,x86上的所有barrier StoreStore、LoadLoad和LoadStore都是无操作的。除了可以通过mfence或cpuid实现的StoreLoad或locked insn。你可以用你的汇编代码来确认。其他障碍仅仅意味着对编译器优化和转换的限制,这样它们就不会破坏java内存模型规范。
当您在英特尔处理器上运行时,我假设它的x86。
请阅读
> < Li > < p > http://gee . cs . OS wego . edu/dl/jmm/cookbook . html以供参考。
http://psy-lob-saw.blogspot.com/2013/08/memory-barriers-are-not-free.html
锁定不是一个指令,而是一个指令前缀(表现为存储负载屏障)。
在阅读了这个问题和这个(尤其是第二个答案)之后,我对volatile及其关于记忆障碍的语义感到非常困惑。 在上面的例子中,我们写入一个易失性变量,这会导致一个mitch,这反过来会将所有挂起的存储缓冲区/加载缓冲区刷新到主缓存,使其他缓存行无效。 然而,非易失性字段可以优化并存储在寄存器中,例如?那么,我们如何才能确保给定一个写入易失性变量之前的所有状态变化都是可见的呢?如果我们有1000件东西呢
本文向大家介绍易语言怎么输入负数?易语言输入负数的方法,包括了易语言怎么输入负数?易语言输入负数的方法的使用技巧和注意事项,需要的朋友参考一下 易语言怎么输入负数,我试过在数字前加 - 符号发现不行,后来找到了输入方法,我一步步教给大家。 1、打开易语言新建一个windows程序点击进入代码编辑区 2、我们这里用到一个命令就是取整 3、这个函数比较简单就一个参数输入小数就行 我们输入9.19
问题内容: 我尝试了解为什么此示例是正确同步的程序: 由于存在冲突的访问(存在对a的写入和读取),因此在每个顺序一致性中,必须在访问之间的关系之前执行。假设顺序执行之一: 是1发生-在2之前发生,为什么? 问题答案: 不,在相同变量的易失性写入之前(以同步顺序),在易失性写入 之前 不一定 会发生 易失性读取。 这意味着它们可能处于“数据争用”中,因为它们“冲突的访问未按先发生后关系进行排序”。如
我正在设置AWS弹性豆茎应用程序,我希望它的流量是HTTPS。 我创建了一个与beanstalk url匹配的DNS CNAME记录,并在AWS证书管理器中为该DNS名称创建并批准了一个证书。 现在,我转到Elastic Beanstalk Environment-->Configuration-->Network Tier/Load Balancer(下图),以便将“安全侦听器端口”从OFF设置
所有的中断函数都能正常工作,但是过程函数却让我很生气。 我会感激任何我没注意的把戏。
当我在jdk1.8中阅读时,我看到方法具有易失性读写的内存语义学的注释。 注释和代码如下: 在AbstractQueuedSynchronizer类中,是一个名为 只是想知道如果是一个非易失性成员,记忆语义学是什么。
问题内容: 如何使数组易失?因为正如我所了解的那样,使数组易失是不安全的吗? 问题答案: 将数组声明为volatile并 不能 对其字段进行volatile访问。您是在声明引用本身是可变的,而不是元素。 换句话说,你声明 挥发性组 的元素,而不是一个 集易挥发元素 。 解决方案是在要使用整数的情况下使用。另一种方法(但有点难看)是每次您编辑字段时都将对数组的引用重写。 您可以这样做: (就像我说的