ArrayBlockingQueue 源码阅读 问题(一)
2014-04-23 22:47
162 查看
今天阅读java.util.concurrent 中 ArrayBlockingQueue 的源码,发现其中有很多下面这行代码
final ReentrantLock lock = this.lock
对此行代码非常疑惑,为什么不直接使用this.lock 呢?为什么要使用局部变量呢?于是使用强大的谷歌搜了一把,发现下面两种答案
1. concurrent包的作者Doug Lea 在邮件当中的回复
It’s ultimately due to the fundamental mismatch between memory models
and OOP
Just about every method in all of j.u.c adopts the policy of reading fields as locals whenever a value is used more than once.This way you are sure which value applies when.This is not often pretty, but is easier to visually verify.
The surprising case is doing this even for “final” fields.This is because JVMs are not always smart enough to exploit the fine points of the JMM and not reload read final values, as they would otherwise need to do across the volatile accesses entailed in locking. Some JVMs are smarter than they used to be about this, but still not always smart enough.
个人E文不好,java水平有限,难以理解
2. 这样写,一般是因为引用的变量(一般是类的成员变量)是可变的。通过在栈上增加一个变量来引用这个可变域,可以防止在以后的操作中,由于其他的并发修改操作导致这个可变域在多次访问中引用值不一致,从而最终导致数据不一致。
补充一下,性能上的可能优化点:
1、this.lock是类的成员变量,一般都是存到堆上,访问堆上的变量会涉及内存同步的操作(这个建议通过编译后的bytecode进行观察),而将其copy到栈上,然后访问就不存在这个问题了;
在访问堆上的this.lock时,对于多个CPU,可能会存在cache命中的问题,这样必然会导致内存重新load,而copy到栈上,则直接是线程相关的,就不存在这个问题了。
答案2似乎比较容易理解一些,似懂非懂吧,先记录下来。
final ReentrantLock lock = this.lock
对此行代码非常疑惑,为什么不直接使用this.lock 呢?为什么要使用局部变量呢?于是使用强大的谷歌搜了一把,发现下面两种答案
1. concurrent包的作者Doug Lea 在邮件当中的回复
It’s ultimately due to the fundamental mismatch between memory models
and OOP
Just about every method in all of j.u.c adopts the policy of reading fields as locals whenever a value is used more than once.This way you are sure which value applies when.This is not often pretty, but is easier to visually verify.
The surprising case is doing this even for “final” fields.This is because JVMs are not always smart enough to exploit the fine points of the JMM and not reload read final values, as they would otherwise need to do across the volatile accesses entailed in locking. Some JVMs are smarter than they used to be about this, but still not always smart enough.
个人E文不好,java水平有限,难以理解
2. 这样写,一般是因为引用的变量(一般是类的成员变量)是可变的。通过在栈上增加一个变量来引用这个可变域,可以防止在以后的操作中,由于其他的并发修改操作导致这个可变域在多次访问中引用值不一致,从而最终导致数据不一致。
补充一下,性能上的可能优化点:
1、this.lock是类的成员变量,一般都是存到堆上,访问堆上的变量会涉及内存同步的操作(这个建议通过编译后的bytecode进行观察),而将其copy到栈上,然后访问就不存在这个问题了;
在访问堆上的this.lock时,对于多个CPU,可能会存在cache命中的问题,这样必然会导致内存重新load,而copy到栈上,则直接是线程相关的,就不存在这个问题了。
答案2似乎比较容易理解一些,似懂非懂吧,先记录下来。
相关文章推荐
- ArrayBlockingQueue源码阅读心得
- JDK 1.8 ArrayBlockingQueue 源码阅读(二)获取
- ArrayBlockingQueue源码阅读
- 阅读ArrayBlockingQueue源码了解如何利用锁实现BlockingQueue
- J.U.C并发框架源码阅读(八)ArrayBlockingQueue
- ArrayBlockingQueue 源码阅读与分析
- java1.7集合源码阅读:ArrayBlockingQueue
- 《java.util.concurrent 包源码阅读》06 ArrayBlockingQueue
- java源码阅读之ArrayBlockingQueue
- ArrayBlockingQueue源码阅读与理解
- JDK 1.8 ArrayBlockingQueue 源码阅读(一)插入
- 深入理解阻塞队列(二)——ArrayBlockingQueue源码分析
- 关于java ArrayBlockingQueue 源码解析的小疑惑
- ArrayBlockingQueue源码分析
- ArrayBlockingQueue源码解读
- ArrayBlockingQueue源码剖析
- 阻塞队列和ArrayBlockingQueue源码解析
- 源码分析-ArrayBlockingQueue
- Java ArrayBlockingQueue 源码
- 《java.util.concurrent 包源码阅读》19 PriorityBlockingQueue