首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程缓存和Java内存模型

线程缓存和Java内存模型
EN

Stack Overflow用户
提问于 2013-12-13 03:54:43
回答 4查看 17.7K关注 0票数 28

我正在尝试理解Java内存模型和线程。据我所知,每个线程都有一个“主”内存的本地副本。因此,如果一个线程试图更改某个对象的int变量,它会缓存int变量,如果它更改了该变量,其他线程可能看不到更改。

但是如果线程缓存的是某个对象而不是int呢?在这种情况下,哪些线程会缓存它?如果线程缓存了对对象的引用,那么对该对象状态的任何更改对其他线程都是不可见的吗?为什么?

EN

回答 4

Stack Overflow用户

发布于 2013-12-13 05:26:04

CPU有不同级别的缓存L1、L2、L3。每个CPU (以及/may CPU Core)都有自己的缓存。此高速缓存存储最小的主内存(RAM)集以提高性能。

代码语言:javascript
复制
  _______________    ______________  
 |     CPU 1     |  |     CPU 2    |  
 |   _________   |  |   _________  |  
 |  | Level 1 |  |  |  | Level 1 | |  
 |  |   Cache |  |  |  |  Cache  | |  
 |  |         |  |  |  |         | |
 |  |_________|  |  |  |_________| |  
 |_______________|  |______________|
           | |              | |
           | |              | |
          _|_|______________|_|__
         |                       |
         |      MAIN MEMORY      | 
         |_______________________|


  Time     Command                 CPU 1 (Cache)      CPU 2 (Cache)        Main Memory     
-------  ----------              ----------------    --------------       -------------
  1          ---                       ---                ---                x = 10
  2       Read x  (on cpu1)           x = 10              ---                x = 10
  3       Write x <--20 (on cpu1)     x = 20              ---                x = 10       
  4       Read  x (on cpu2)           x = 20              x = 10             x = 10
  5       put cache to Main mem       x = 20              x = 10             x = 20

例如,在执行顺序上,x值在CPU2上是错误的。X值已被CPU1更改。如果x变量被定义为易失性,则所有写操作立即反映到主存储器。

票数 33
EN

Stack Overflow用户

发布于 2013-12-13 04:02:50

=============================================================

由于许多原因,下面的答案是错误的。请不要使用任何其他目的,而不是有一个爆炸。现代CPU上的缓存始终是一致的。

=============================================================

线程没有内存的本地副本。线程读/写的存储器的一部分可以来自高速缓存,而不是主存储器。缓存不需要彼此同步,也不需要与主内存同步。所以这就是你可以观察到的不一致之处。

,因此,如果一个线程试图更改一个int变量,例如某个对象,它会缓存该int变量,而如果它更改了该变量,其他线程可能看不到更改。

这是正确的。Java内存模型在先于规则发生中定义,例如,在字段x的易失性写入和字段x的易失性读取之间存在先于发生的规则。因此,当写入完成时,后续读取将看到写入的值。

如果没有这样的先行关系,所有的赌注都会失效(另外,当没有先行规则时,指令重新排序可能会使情况变得复杂)。

如果线程缓存了对对象的引用,对对象状态的任何更改对其他线程也是不可见的吗?为什么?

它可能是可见的..。它也可能是不可见的。如果没有先于规则发生,所有的赌注都是。原因是,否则许多优化,如硬件技巧,以加快速度,或编译器技巧将是不允许的。当然,总是保持内存与缓存同步会降低性能。

===========================================================

票数 13
EN

Stack Overflow用户

发布于 2013-12-13 05:15:16

CPU有多个缓存。正是这些硬件缓存可能具有不一致的数据副本。它们可能不一致的原因是,保持所有内容的一致性会使您的代码减慢10倍,并破坏您从拥有多个线程中获得的任何好处。要获得良好的性能,您需要有选择地保持一致。Java内存模型描述了何时确保数据的一致性,但在最简单的情况下,它不会。

注意:这不仅仅是CPU的问题。不需要在线程之间保持一致的字段可以在代码中内联。这可能意味着,如果一个线程更改了该值,另一个线程可能永远不会看到这个更改,因为它已经被写入代码中。

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

https://stackoverflow.com/questions/20552945

复制
相关文章

相似问题

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