use*_*534 24 java garbage-collection memory-management
我正在尝试理解Java内存模型和线程.据我所知,每个线程都有一个"主"内存的本地副本.因此,如果一个线程试图更改一个int
变量(例如某个对象),它会缓存该int
变量,如果它更改了变量,则其他线程可能看不到变化.但是如果线程缓存某些对象而不是int呢?在这种情况下,哪些线程会缓存它?如果一个线程缓存对象的引用,对对象状态的任何更改都不会被其他线程看到?为什么?
先感谢您
Erd*_*kın 29
CPU具有不同级别的高速缓存L1,L2,L3.每个CPU(以及/或CPU核心)都有自己的缓存.此高速缓存存储最小的主存储器(RAM)以提高性能.
_______________ ______________
| 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
Run Code Online (Sandbox Code Playgroud)
例如,在执行顺序上,CPU2上的x值是错误的.x值已由CPU1更改.如果x变量定义为volatile,则所有写操作立即反映到主存.
pve*_*jer 14
线程没有内存的本地副本.线程读/写的部分内存可以来自缓存,而不是主内存.缓存不需要彼此同步,也不需要与主存储器同步.所以这是你可以观察到不一致的地方.
因此,如果一个线程试图更改一个int变量,例如某个对象,它会缓存int变量,如果它更改它,其他线程可能看不到更改.
那是正确的.Java存储器模型在规则之前定义,例如,在字段x的易失性写入和字段x的易失性读取之间的规则之前发生.因此,当写入完成后,后续读取将看到写入的值.
如果在关系之前没有这样的事情发生,所有的赌注都会被取消(当规则之前没有发生时,指令重新排序也会使生活变得复杂).
如果线程缓存对对象的引用,对对象状态的任何更改对其他线程也不可见?为什么?
它可能是可见的......它也可能不可见.所有投注都没有在规则之前发生.之所以如此,那么很多优化就像硬件技巧一样加快速度,或者不允许使用编译器技巧.当然,始终保持内存与缓存同步会降低性能.
Pet*_*rey 13
CPU有多个缓存.正是这些硬件缓存可能具有不一致的数据副本.它们可能不一致的原因是保持一致性会使代码速度降低10倍,并破坏从多线程中获得的任何好处.要获得不错的性能,您需要选择性地保持一致.Java内存模型描述了它何时确保数据是一致的,但在最简单的情况下却没有.
注意:这不仅仅是CPU问题.可以在代码中内联不必在线程之间保持一致的字段.这可能意味着如果一个线程更改了该值,则另一个线程可能永远不会看到此更改,因为它已被烧入代码中.
归档时间: |
|
查看次数: |
13729 次 |
最近记录: |