JSR133中volatile关键字的理解,有一个地方很迷惑

The original semantics forvolatile guaranteed only that reads and writes ofvolatile fields would be made directly to main memory, instead of to registers or the local processor cache, and that actions on volatile variables on behalf of a thread are performed in the order that the thread requested. In other words, this means that the old memory model made promises only about the visibility of the variable being read or written, and no promises about the visibility of writes to other variables. While this was easier to implement efficiently, it turned out to be less useful than initially thought.

While reads and writes of volatile variables could not be reordered with reads and writes of other volatile variables, they could still be reordered with reads and writes of nonvolatile variables. InPart 1 , you learned how the code in Listing 1 was not sufficient (under the old memory model) to guarantee that the correct value forconfigOptions and all the variables reachable indirectly throughconfigOptions (such as the elements of theMap ) would be visible to thread B, because the initialization ofconfigOptions could have been reordered with the initialization of the volatileinitialized variable.

Map configOptions; char[] configText; volatile boolean initialized = false; // In Thread A configOptions = new HashMap(); configText = readConfigFile(fileName); processConfigOptions(configText, configOptions); initialized = true; // In Thread B while (!initialized) sleep(); // use configOptions

Unfortunately, this situation is a common use case for volatile -- using a volatile field as a "guard" to indicate that a set of shared variables had been initialized. The JSR 133 Expert Group decided that it would be more sensible for volatile reads and writes not to be reorderable with any other memory operations -- to support precisely this and other similar use cases. Under the new memory model, when thread A writes to a volatile variable V, and thread B reads from V, any variable values that were visible to A at the time that V was written are guaranteed now to be visible to B. The result is a more useful semantics ofvolatile , at the cost of a somewhat higher performance penalty for accessing volatile fields.

volatile的语义:

1. 确保对volatile域的读写操作都是直接在主存内进行,不缓存到线程的本地内存中。

2. 在旧的JMM中,volatile域的操作与nonvolatile域的操作之间可以重新排序。但是在JSR133以后,规定volatile操作和其他任何内存操作之间都不允许进行重新排序。

3. 在新的JMM下,当线程A写一个volatile变量V,然后线程B读取V的时侯,任何在写入V时对线程A可见的变量值,都对B可见

第3条很奇怪,感觉有点象synchronized的作用了。是不是线程A写入一个volatile变量时,会将自己的本地缓存中的non-volatile变量刷新到主存中,读一个volatile变量时会更新自己的本地缓存中的non-volatile变量?不然线程B又怎么能够看得见那些nonvolatile变量呢?

关于这个问题,查询了一些资料,有文章认为“volatile字段的读取和写入与进入和退出监视器具有相似的内存一致性效果”(http://blog.csdn.net/lovingprince/archive/2010/04/04/5450246.aspx

对于volatile变量的读写有一个happens-before的偏序关系

A write to a volatile fieldhappens-before every subsequent read of that same volatile. 这点没有疑问。

Because the write of the volatile variableinitialized happens after the initialization ofconfigOptions , the use ofconfigOptions happens after the read ofinitialized , and the read ofinitialized happens after the write toinitialized , you can conclude that the initialization ofconfigOptions by thread A happens before the use ofconfigOptions by thread B. Therefore,configOptions and the variables reachable through it will be visible to thread B.

在新JMM中使用volatile,可以确保上面的代码是合理的。以下"<"是happens-before的意思

1. “线程A中configOptions初始化” < “线程A中写initialized变量”

2.“线程B中读initialized变量” < “线程B中使用configOptions”

3. “write to volatile field” < “subsequent read of that same volatile”

并且有 action1 < action 2,action2 < action3,那么action1 < action3

所以我们可以得出:“线程A中configOptions初始化”< “线程B中使用configOptions”

也就是说,在使用了volatile变量后,使得non-volatile变量的操作之间也有了happens-before关系。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值