【发布时间】:2017-06-29 01:01:35
【问题描述】:
我对同步块毫无疑问。 在我提出问题之前,我想分享另一篇相关帖子Link for Answer to related question 的答案。我从同一个答案中引用Peter Lawrey。
同步可确保您拥有一致的数据视图。这意味着您将读取最新值,其他缓存将获得 最新值。缓存足够聪明,可以通过 特殊巴士(不是 JLS 要求的,但允许)这个 总线意味着它不必触摸主存储器即可获得 一致的观点。
如果只使用同步,则不需要 volatile。如果您有一个非常简单的操作来同步,那么 Volatile 很有用 会有点矫枉过正。
参考上面我有以下三个问题:
第一季度。假设在多线程应用程序中有一个对象或原始实例字段仅在同步块中读取(写入可能发生在其他一些没有同步的方法中)。同步块也定义在其他一些对象上。 将其声明为 volatile(即使仅在 Synchronized 块中读取)是否有意义?
第二季度。 我了解已完成同步的对象的状态值是一致的。 我不确定在同步块中读取的其他对象和原始字段的状态。 假设更改是在没有获得锁的情况下进行的,但读取是通过获得锁来完成的。同步块中所有对象的状态和所有原始字段的值是否始终具有一致的视图。 ?
第三季度。 [更新]:无论我们锁定什么,在同步块中读取的所有字段都会从主内存中读取吗? [CKing 回答]
我为上述问题准备了参考代码。
public class Test {
private SomeClass someObj;
private boolean isSomeFlag;
private Object lock = new Object();
public SomeClass getObject() {
return someObj;
}
public void setObject(SomeClass someObj) {
this.someObj = someObj;
}
public void executeSomeProcess(){
//some process...
}
// synchronized block is on a private someObj lock.
// inside the lock method does the value of isSomeFlag and state of someObj remain consistent?
public void someMethod(){
synchronized (lock) {
while(isSomeFlag){
executeSomeProcess();
}
if(someObj.isLogicToBePerformed()){
someObj.performSomeLogic();
}
}
}
// this is method without synchronization.
public void setSomeFlag(boolean isSomeFlag) {
this.isSomeFlag = isSomeFlag;
}
}
【问题讨论】:
-
我想对这件事说得很好,但这是诚实最有效的事情之一。如果您在谈论您拥有的 JMM 时正在考虑诸如“从内存中获取”之类的事情'不理解它,应该远离并发。但是没有给出的代码是不正确的。
-
@ControlAltDel 不,简单地使
isSomeFlagvolatile 不会解决此代码的问题。您还在someObj上进行了数据竞赛,这意味着someMethod()在访问someObj....时可能会看到乱码。 (“在此处添加 volatile”几乎总是危险的建议。) -
@BrianGoetz 这很顺利。 [我不敢相信我亲眼目睹了这一点;)]
-
@CKing 是的,这有点像唐·克努斯(Don Knuth)在你的算法作业上得到帮助,甚至没有注意到:-)
-
@CKing 我想说实际上说这根本不重要 :-) 虽然在 Wikipedia 上查找他可能会花费 15 分钟,但他是一个非常有趣的角色。
标签: java multithreading heap-memory synchronized-block