首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java内存模型与并发性

Java内存模型与并发性
EN

Stack Overflow用户
提问于 2015-11-29 18:58:50
回答 3查看 290关注 0票数 1

考虑到Java模型中的x86总存储顺序和发生之前的关系,我们知道编译器并不保证指令的执行顺序。它可以根据需要重新排序,以提高性能。有鉴于此,我们有:

  • EAXEBX是寄存器的名称
  • [x][y]是内存位置
  • r1r2是局部变量的名称。
  • xy是所有线程都可以访问的共享变量。所有变量都是32位整数.
  • 不,这不是作业问题。

因此,我有两个问题,我试图确定可能的输出:

代码语言:javascript
复制
[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]

哪些是寄存器EBXEAX的可能值?

代码语言:javascript
复制
int x = 0;
int y = 0;

// Thread 1                         Thread 2
x = 1;                              y = 1; 
r1 = y;                             r2 = x;

r1r2的可能值是多少?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-11-29 19:21:22

编写32-bit integerJVM保证为atomic,所以这不是一个问题。

在没有synchronization的线程之间共享两个变量x和y。

  1. Thread1会变异x并读取y。
  2. Thread2变异y并读取x。

因此,thread1可以看到陈旧值y (1或0),而thread2可以看到陈旧值x (1,0)。

这意味着您可以得到所有四个可能的组合(eax,ebx):(0,0) (0,1) (1,0) (1,1)

票数 4
EN

Stack Overflow用户

发布于 2015-11-29 20:43:49

x86有一个强有序内存模型,但仍然允许StoreLoad重排

Jeff的博客文章:该法案中的内存重新排序正是使用这对存储加载序列作为测试用例来证明重新排序确实可以在真实的硬件上观察到。他有源代码什么的。

注意,每个线程都有自己的体系结构状态(包括所有寄存器)。因此,线程1的EAX不同于线程2的EAX。在thread2中使用EBX只会使人们更容易谈论,而不是什么可能发生的POV。

无论如何,这两个寄存器都可能以0结尾。这种情况很少发生,但可以,因为每个线程的存储可以延迟(存储缓冲区或其他什么),直到另一个线程的加载选择了一个值之后。这是合法的,让CPU积极地使用预取的数据来满足负载,并缓冲存储,这样,当它们退役时,它们可能不会立即成为全局可见的。(“退休”是指运行指令的线程的体系结构状态(包括EIP)已转移到下一条指令,并提交了效果。)

其他可能性,一旦尘埃落定,总是包括两个全球都是1。每个线程寄存器中的所有4个可能值为零和一个是可能的,包括两个1。他们有可能看到对方的商店。我不确定这有多大的可能性;它可能需要在其存储之后但在加载之前中断一个线程。如果两个线程运行在同一个物理内核(超线程)上,这种可能性要大得多

即使xy的存储是不对齐的,并且跨越缓存线,01也是唯一可能的值。(C编译器输出和JVM将变量与它们的自然对齐方式对齐,这是一个没有问题的问题,但是在asm中你可以做任何你想做的事情,所以我想我应该提一下。)之所以会出现这种情况,是因为这两个值仅在最小有效字节中存在差异。

如果要将32位-1存储到跨越两条缓存行的4字节,则另一个线程可以加载0x00ffffff0xff0000000x0000ffff0xffff0000等的值(取决于缓存行边界的位置),以及通常的00xffffffff (又名-1)。

re: Java。我还没有读过Java内存模型。其他的答案是,它甚至允许编译时重新排序(比如C++11的std::原子规则)。即使没有完全的内存屏障,StoreLoad重新排序也可能发生。因此,所有四个结果都是可能的,

即使您的JVM运行在x86 CPU上(而不是像ARM这样排序不严格的硬件),情况也是如此。

对另一个问题的回答可能解释了为什么LFENCE/SFENCE在x86上存在,尽管它们在大多数情况下都是无操作的。(即不使用movnt或弱有序内存区域(如USWC视频存储器))。

或者,阅读的其他博客文章,了解更多关于内存排序的信息。我觉得这真的很有帮助。

票数 4
EN

Stack Overflow用户

发布于 2015-11-29 19:12:34

我们可以简单地将语句标签如下:

代码语言:javascript
复制
A) [x] <- 1            C) [y] <- 1

B) EAX <- [y]           D) EBX <- [x]

我们知道A在B前面,C在D前面,所以只要在所有可能的排列中将C和D插入AB:

代码语言:javascript
复制
CDAB
CADB
CABD
ACDB
ACBD
ABCD

并考虑每种可能性的含义,注意到大多数都是从ACCA开始,输出(EAX,EBX)=(1,1),因为作业发生在EAXEBX设置之前。剩下的就是检查另外两种可能性。CDAB(EAX,EBX)=(1,0)ABCD(EAX,EBX)=(0,1)

对于Java版本,您可以声明编译器并不保证执行语句的顺序。在这种情况下,应该不难命令ABCD得到(0,0)、(1,0)、(0,1)和(1,1)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33986709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档