-
为什么线程要保存共享成员变量的私有拷贝?3
"Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。"
为什么保存私有拷贝,速度就能提升呢?
还有,这个私有拷贝保存在哪里?frame中的local variable吗?
如果这个共享成员是非primitive的对象,那是不是还要在heap中深克隆这个对象吗?
问题补充:
"每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。"
JVM的内存模型需要考虑cpu的缓存吗?我以为JVM为每条线程创建的工作内存也是在内存上,所以我就不明白为什么要copy一分到工作内存以提高性能?2009年9月10日 15:21
3个答案 按时间排序 按投票排序
-
采纳的答案
因为概念上是“一份”的内存实际上未必只有一份……
假象下述情况:一个对象被两个线程共享,而这两个线程分别在两个核上同时执行,并且两个核的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
-
很多概念都容易混淆……我觉得分清楚抽象层次来思考问题会是个好习惯。就像平时说的程序用的“内存”,在支持虚拟内存的系统上其实并不是指“物理内存”,申请了内存空间也跟“占用了物理内存”没有直接关系。
2009年9月10日 16:34
-
"working memory"是JVM规范的一个抽象概念,跟实际上是在物理内存还是在高速缓存里没有直接关系。但可以肯定的是,这里关于线程的“working memory”对许多平台来说都是对高速缓存的抽象。规范不能把implementation-specific的东西写进去,不然会影响实现难度和可移植性。
2009年9月10日 16:30
相关推荐
Java语言规范中指出:为了获得佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。 这样当多个线程同时与某个对象交互时,必须要注意到要让线程...
首先要将变量从主内存拷贝到自己的工作内存空间,然后对变量操作,操作完成后再将变量写入主内存 不能直接操作主内存中的变量 各个线程的工作内存中存储主内存中的变量副本拷贝 因此不同的线程之间无法访问对方的...
Python迭代器生成器,私有变量及推导式(二) Python装饰器AOP 不定长参数 鸭子类型 重载(三) Python新式类 new init 单例模式与作用域(四) Python 进程线程协程 GIL 闭包 与高阶函数(五) Python中深浅拷贝 垃圾回收...
为什么? int n; if (n == 10) // 第一种判断方式 if (10 == n) // 第二种判断方式 如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了= -------------------------------------------------...
你所写入的一切东西都将在这里,而且你原先的指向映射文件的内存地址也会实际指向这段重新分配的内存,于是在进程结束后,映射文件内容并没有改变,只是在运行期间在那段私有拷贝的内存里面存在着你修改的内容。...
我没有做测试,以下是几点说明:1)自行修改“传送文件”Button的OnClick事件2)注意往不同的机子传送时,要为线程中的私有变量设置相应的IP地址和端口,同时将Server.exe拷贝到这台机子上3)可以进行异步创送,即No...
10.11 到底为什么要异常 10.12 异常和sys模块 10.13 相关模块 10.14 练习 第11章 函数和函数式编程 11.1 什么是函数? 11.2 调用函数 11.3 创建函数 11.4 传递函数 ...
10.11 到底为什么要异常 10.12 异常和sys模块 10.13 相关模块 10.14 练习 第11章 函数和函数式编程 11.1 什么是函数? 11.1.1 函数vs过程 11.1.2 返回值与函数类型 11.2...
10.11 到底为什么要异常 10.12 异常和sys模块 10.13 相关模块 10.14 练习 第11章 函数和函数式编程 11.1 什么是函数? 11.1.1 函数vs过程 11.1.2 返回值与函数类型 11.2...
2.1 为什么要平台无关 2.2 Java的体系结构对平台无关的支持 2.2.1 Java平台 2.2.2 Java语言 2.3.3 Java class文件 . 2.2.4 可伸缩性 2.3 影响平台无关性的因素 2.3.1 Java平台的部署 2.3.2 Java平台...
3.3 轻量级进程设计——要考虑的问题 3.3.1 fork 的语义 3.3.2 其他的系统调用 3.3.3 信号传递和处理 3.3.4 可视性 3.3.5 堆栈增长 3.4 用户级线程库 3.4.1 编程接口 3.4.2 线程库的实现 3.5 调度器调用 3.6 Solaris...
2.1 为什么要平台无关 2.2 Java的体系结构对平台无关的支持 2.2.1 Java平台 2.2.2 Java语言 2.3.3 Java class文件 2.2.4 可伸缩性 2.3 影响平台无关性的因素 2.3.1 Java平台的部署 2.3.2 ...
2.1 为什么要平台无关 2.2 Java的体系结构对平台无关的支持 2.2.1 Java平台 2.2.2 Java语言 2.3.3 Java class文件 . 2.2.4 可伸缩性 2.3 影响平台无关性的因素 2.3.1 Java平台的部署 2.3.2 ...
2.1 为什么要平台无关 2.2 java的体系结构对平台无关的支持 2.2.1 java平台 2.2.2 java语言 2.3.3 java class文件 2.2.4 可伸缩性 2.3 影响平台无关性的因素 2.3.1 java平台的部署 2.3.2 ...
各参数声明要与其定义一致。 请参考易语言安装目录内的例程:samples\静态编译\调用LIB和OBJ 1. 静态编译方面的改进和优化。 2. 符号重命名程序(resym.exe)增加对.obj文件的支持,并更新了文档(sdk\static_docs...
第五章 变量和常量 .44 5.1 变 量 .44 5.2 常 量 .46 5.3 小 结 .47 第六章 类 型 转 换 .48 6.1 隐式类型转换 .48 6.2 显式类型转换 .53 6.3 小 结 .56 第七章 表 达 式 .58 7.1 操 作 符 .58 ...