考虑到Java模型中的x86总存储顺序和发生之前的关系,我们知道编译器并不保证指令的执行顺序。它可以根据需要重新排序,以提高性能。有鉴于此,我们有:
EAX,EBX是寄存器的名称[x],[y]是内存位置r1和r2是局部变量的名称。x、y是所有线程都可以访问的共享变量。所有变量都是32位整数.因此,我有两个问题,我试图确定可能的输出:
[x] == [y] == 0 // the address space of [x] and [y] are 0.
// Thread 1 Thread 2
MOV [x] <- 1 MOV [y] <- 1
MOV EAX <- [y] MOV EBX <- [x]哪些是寄存器EBX和EAX的可能值?
int x = 0;
int y = 0;
// Thread 1 Thread 2
x = 1; y = 1;
r1 = y; r2 = x;r1和r2的可能值是多少?
发布于 2015-11-29 19:21:22
编写32-bit integer被JVM保证为atomic,所以这不是一个问题。
在没有synchronization的线程之间共享两个变量x和y。
Thread1会变异x并读取y。Thread2变异y并读取x。因此,thread1可以看到陈旧值y (1或0),而thread2可以看到陈旧值x (1,0)。
这意味着您可以得到所有四个可能的组合(eax,ebx):(0,0) (0,1) (1,0) (1,1)
发布于 2015-11-29 20:43:49
x86有一个强有序内存模型,但仍然允许StoreLoad重排。
Jeff的博客文章:该法案中的内存重新排序正是使用这对存储加载序列作为测试用例来证明重新排序确实可以在真实的硬件上观察到。他有源代码什么的。
注意,每个线程都有自己的体系结构状态(包括所有寄存器)。因此,线程1的EAX不同于线程2的EAX。在thread2中使用EBX只会使人们更容易谈论,而不是什么可能发生的POV。
无论如何,这两个寄存器都可能以0结尾。这种情况很少发生,但可以,因为每个线程的存储可以延迟(存储缓冲区或其他什么),直到另一个线程的加载选择了一个值之后。这是合法的,让CPU积极地使用预取的数据来满足负载,并缓冲存储,这样,当它们退役时,它们可能不会立即成为全局可见的。(“退休”是指运行指令的线程的体系结构状态(包括EIP)已转移到下一条指令,并提交了效果。)
其他可能性,一旦尘埃落定,总是包括两个全球都是1。每个线程寄存器中的所有4个可能值为零和一个是可能的,包括两个1。他们有可能看到对方的商店。我不确定这有多大的可能性;它可能需要在其存储之后但在加载之前中断一个线程。如果两个线程运行在同一个物理内核(超线程)上,这种可能性要大得多。
即使x和y的存储是不对齐的,并且跨越缓存线,0和1也是唯一可能的值。(C编译器输出和JVM将变量与它们的自然对齐方式对齐,这是一个没有问题的问题,但是在asm中你可以做任何你想做的事情,所以我想我应该提一下。)之所以会出现这种情况,是因为这两个值仅在最小有效字节中存在差异。
如果要将32位-1存储到跨越两条缓存行的4字节,则另一个线程可以加载0x00ffffff或0xff000000、0x0000ffff或0xffff0000等的值(取决于缓存行边界的位置),以及通常的0或0xffffffff (又名-1)。
re: Java。我还没有读过Java内存模型。其他的答案是,它甚至允许编译时重新排序(比如C++11的std::原子规则)。即使没有完全的内存屏障,StoreLoad重新排序也可能发生。因此,所有四个结果都是可能的,。
即使您的JVM运行在x86 CPU上(而不是像ARM这样排序不严格的硬件),情况也是如此。
对另一个问题的回答可能解释了为什么LFENCE/SFENCE在x86上存在,尽管它们在大多数情况下都是无操作的。(即不使用movnt或弱有序内存区域(如USWC视频存储器))。
或者,阅读的其他博客文章,了解更多关于内存排序的信息。我觉得这真的很有帮助。
发布于 2015-11-29 19:12:34
我们可以简单地将语句标签如下:
A) [x] <- 1 C) [y] <- 1
B) EAX <- [y] D) EBX <- [x]我们知道A在B前面,C在D前面,所以只要在所有可能的排列中将C和D插入AB:
CDAB
CADB
CABD
ACDB
ACBD
ABCD并考虑每种可能性的含义,注意到大多数都是从AC或CA开始,输出(EAX,EBX)=(1,1),因为作业发生在EAX和EBX设置之前。剩下的就是检查另外两种可能性。CDAB给(EAX,EBX)=(1,0),ABCD给(EAX,EBX)=(0,1)。
对于Java版本,您可以声明编译器并不保证执行语句的顺序。在这种情况下,应该不难命令A、B、C和D得到(0,0)、(1,0)、(0,1)和(1,1)。
https://stackoverflow.com/questions/33986709
复制相似问题