RE:关于JMM模型中工作内存、主内存和几个操作的理解打捞回帖、回信来发博客是个偷懒的好办法 ZZZzzz....ZZZz
RE:关于JMM模型中工作内存、主内存和几个操作的理解
打捞回帖、回信来发博客是个偷懒的好办法
ZZZzzz....ZZZzzz....
------------------------
主内存和工作内存是什么,在这段前面的2节里面有更详细的介绍,内容太多我就不全部粘贴了,反正还有2周书就应该能出来。我做个类比可能好理解一些,简单来说你可以把它们的关系理解成PC机里面的“内存”和“处理器Cache”之间的关系,所有数据在内存中都用,但是要用的时候Cache中都有一份拷贝,如果是多CPU或者多核处理器,同一份数据还可能在不同的Cache中还有拷贝,解决内存与Cache的一致性问题,硬件里有各种一致性协议。而JVM的内存模型其中一个任务也是解决main memory和working memory之间的一致性问题。
“thread's working copy of a variable”不是局部变量,它就是工作内存中的变量拷贝副本而已,事实上在JMM中一开始就从定义了“variable”的含义,它包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的 ,不会被共享,自然就不存在竞争问题。
关于为何store之后又要write的问题,从上面图片你可以看到,这2个操作是作用在不同区域上的,你把main memory和work memory看作2间房子,这2个操作就好比开门,要把物品A从房间以拿到(复制到)房间B,自然要分别进行“拿出来”和“放进去”2个操作。为什么不定义一个诸如transfer之内的操作一次过完成呢?那是因为这6个操作都是“原子的”,不可拆分,如果定义一个原子的“transfer”操作当然也可以完成任务,但原子操作的范围更大,也就意味这个操作的锁定时间更长。这与JMM规范的基本思想:既准确又宽松(见下面图片)相违背了。

哈哈哈,我一看到站内信中“不要把抽象概念与具体实现混为一谈”这句,脑子里就冒出一个念头,这话8成是撒迦说的。
嘿嘿,感觉世界好小
哈哈哈,我一看到站内信中“不要把抽象概念与具体实现混为一谈”这句,脑子里就冒出一个念头,这话8成是撒迦说的。
嘿嘿,感觉世界好小,谢谢两位
不不不…你看的是JVMS2么?不要看那份了,那是JDK 1.2时代的。
看这个:http://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index3.html
我上面给的链接是JVMS3的草案。看这段:
不不不…你看的是JVMS2么?不要看那份了,那是JDK 1.2时代的。
看这个:http://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index3.html
说起JVMS3,有没有小道消息这规范的正式版啥时候出来呀?
Addison-Wesley出版社回信说:
这个FAQ确实很不错,以前也看过
我一直认为要看的JAVA规范是JLS 3rd 和 JVMS 2nd呢,我们用的JDK1.5
hi 撒加 & IcyFenix ,弱弱的问几个低级的问题:
1. 所谓主内存中的数据,我的理解应该即是一个Object的一些属性数据(当然会有情况出现栈上分配)。
public class Volatile {public String name ;public volatile int id = 1; public static void main(String args[]) {Volatile v = new Volatile();v.name = "a";v.id++;System.out.println(v.name);System.out.println(v.id);}}按照这样的代码,对id属性的访问理论上满足从主内存到工作内存的交换。但bytecode中,仅仅出现getfiled/putfield的指令。
对应的指令:
14:aload_1 15:dup 16:getfield#2; //Field id:I 19:iconst_1 20:iadd 21:putfield#2; //Field id:I
不知道blog中所提到的规范中:read/load, store/write的体现是在哪?
是不是getfield的指令实现时会拆分成read/load的两个动作
2. use/assign的理解。 类比一下操作系统的一些概念,类似于操作数寄存器。 load/store的操作只是针对局部变量区,类似于cpu cache。主内存类似于memory的访问
3. volitile的可见性的体现。 因为在看生成的bytecode中getfield/putfield中并没有啥特殊的处理,唯一的就是在对应的field信息中保留了volatile信息。那是不是意味着具体的可见性的处理,会体现在getfield针对不同类型的处理上。
先前仔细看了JLS后,联系到具体的实现,问题比较多,望能给与解惑。
2. A store operation by T on V is permitted only if the previous operation by T on V was assign, and an assign operation by T on V is permitted only if the next operation by T on V is store. The assign operation is said to be "associated" with the write operation that corresponds to the store.
3. Let action A be a use or assign by thread T on variable V, let action F be the load or store associated with A, and let action P be the read or write of V that corresponds to F. Similarly, let action B be a use or assign by thread T on variable W, let action G be the load or store associated with B, and let action Q be the read or write of W that corresponds to G. If A precedes B, then P must precede Q. (Less formally: operations on the master copies of volatile variables on behalf of a thread are performed by the main memory in exactly the order that the thread requested.)
关于这个规则,有几个疑问:
class Foo{ int i=1; say(){ int a=i; //1. read(i)->load(i)->use(i) int b=i; //2. use(i)} 1. 在b的us操作之前[read(i)->load(i)]这2步动作是不是可选的? 这个时候用的是Thread Memory第一步缓存的那个i?
2. 而如果i是volatile的那么一定会发生这个几步动作read(i)->load(i)->use(i)?
3. 也就是说要使用volatile之前一定要从Main Memory那里去取?
class Bar{ int valotile i=1; set(int var){ i= var; }public void set(int); Code: Stack=2, Locals=2, Args_size=2 0: aload_0 1: iload_1 2: putfield #18; //Field i:I 5: return} 4. aload_0指的是 read(var)->load(var)这2步动作?
5. aload_1指的是 read(i)->load(i)这2步动作?
6. putfield指的是 use(var)->assign(i)->store(i)->write(i)这几步动作?
按照规范第2条use(var)->assign(i)->store(i)->write(i)这几步一定是同时发生而且一定会发生,当然use(var)->assign(i)这步中间可以有其他指令eg: use(var)-read(c)->load(c)->use(c)>assign(i)?
7.如上面的列子Thread_1.set(10) 同时 Thread_2.set(9),
Thread_1 跟 Thread_2 分别执行的actions序列是这样磨: read(var)->load(var)->read(i)->load(i)->use(i)->use(var)->assign(i)->store(i)->write(i)?
如果是这样的话当Thread_1在执行store(i)->write(i)[写?]之前Thread_2
执行到了这一步(那到了Main Memory的旧值)
read(var)->load(var)->read(i)->load(i)->use(i)->use(var),
当Thread_1写完10,Thread_2再写9? 这跟用不用volatile不时一样吗?
当然volatile可以解决reordering的问题.
问题比较多 2位boss 给点耐心哈,最好出篇这样的文章来帮小弟扫下盲拜托了.... ^^