0 0

为什么线程要保存共享成员变量的私有拷贝?3

"Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。"
为什么保存私有拷贝,速度就能提升呢?
还有,这个私有拷贝保存在哪里?frame中的local variable吗?
如果这个共享成员是非primitive的对象,那是不是还要在heap中深克隆这个对象吗?


问题补充:
"每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。"
JVM的内存模型需要考虑cpu的缓存吗?我以为JVM为每条线程创建的工作内存也是在内存上,所以我就不明白为什么要copy一分到工作内存以提高性能?
2009年9月10日 15:21

3个答案 按时间排序 按投票排序

0 0

采纳的答案

因为概念上是“一份”的内存实际上未必只有一份……
假象下述情况:一个对象被两个线程共享,而这两个线程分别在两个核上同时执行,并且两个核的L1和L2缓存不共享;在“主内存”里,该对象只有一份,但CPU要读取数据需要先把它读到缓存里,因为对数据的访问通常表现出“局部性”,而且缓存速度比主内存快很多,所以这样在许多时候比较快;数据经过了主内存->L2缓存->L1缓存,然后才到CPU进行运算。某个核的缓存不flush到主内存的时候,别的核“看不到”相应的更新;并且,别的核如果不强制从主内存重新读数据到缓存里的话,它也“不去看”相应的更新。于是,如果不做特别的处理,线程间就有可能看到状态不一致的共享数据了。主内存与缓存间的复制关系,就是字节对字节的复制而已,并没有刻意的深拷贝。

Java 5更新了内存模型的规定后,收紧了volatile-read和volatile-write的语义,可以去看看相关资料。

seman18 写道
还有,这个私有拷贝保存在哪里?frame中的local variable吗?

如果你说的“frame”是指JVM规范里关于Java方法调用的frame的话,你可能把不同抽象层次的概念混在一起了。JVM规范里的frame具体要如何实现并不是规范所关心的。事实上frame可能不是整体保存在一个地方,可以一部分在寄存器里一部分在栈上,或者整个在堆上,都没有关系,只要表明上的行为满足规范的规定就行。从这个抽象层次上是涉及不到底下的硬件处理多线程时会遇到的问题的……

2009年9月10日 16:10
0 0

很多概念都容易混淆……我觉得分清楚抽象层次来思考问题会是个好习惯。就像平时说的程序用的“内存”,在支持虚拟内存的系统上其实并不是指“物理内存”,申请了内存空间也跟“占用了物理内存”没有直接关系。

2009年9月10日 16:34
0 0

"working memory"是JVM规范的一个抽象概念,跟实际上是在物理内存还是在高速缓存里没有直接关系。但可以肯定的是,这里关于线程的“working memory”对许多平台来说都是对高速缓存的抽象。规范不能把implementation-specific的东西写进去,不然会影响实现难度和可移植性。

2009年9月10日 16:30

相关推荐

Global site tag (gtag.js) - Google Analytics