2

我对同步块毫无疑问。在我提出问题之前,我想分享另一篇相关帖子的答案链接以回答相关问题。我从同一个答案中引用彼得劳里的话。

  1. 同步可确保您拥有一致的数据视图。这意味着您将读取最新值,而其他缓存将获得最新值。缓存足够聪明,可以通过特殊的总线相互通信(JLS 不需要,但允许)这种总线意味着它不必接触主内存即可获得一致的视图。

  2. 如果只使用同步,则不需要 volatile。如果您有一个非常简单的操作,而同步操作会过大,那么 Volatile 很有用。

参考上面我有以下三个问题:

Q1。假设在多线程应用程序中有一个对象或原始实例字段仅在同步块中读取(写入可能发生在其他一些没有同步的方法中)。同步块也定义在其他一些对象上。将其声明为 volatile(即使仅在 Synchronized 块中读取)是否有意义

Q2。我了解已完成同步的对象状态的值是一致的。我不确定在 Synchronized 块中读取的其他对象和原始字段的状态。假设在没有获得锁的情况下进行了更改,但是通过获得锁来完成读取。同步块内所有对象的状态和所有原始字段的值是否始终具有一致的视图。?

Q3。[更新]无论我们锁定什么,在同步块中读取的所有字段都将从主内存中读取吗?[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;
  }
}
4

3 回答 3

3

您需要了解的第一件事是,链接答案中讨论的场景与您正在谈论的场景之间存在细微差别。您谈到在没有同步的情况下修改值,而所有值都是在链接答案的同步上下文中修改的。考虑到这种理解,让我们解决您的问题:

Q1。假设在多线程应用程序中有一个对象或原始实例字段仅在同步块中读取(写入可能发生在其他一些没有同步的方法中)。同步块也定义在其他一些对象上。将其声明为 volatile(即使仅在 Synchronized 块中读取)是否有意义?

是的,将字段声明为volatile. 由于写入不是在synchronized上下文中发生的,因此无法保证写入线程会将新更新的值刷新到主内存。因此,读取线程可能仍会看到不一致的值。

假设在没有获得锁的情况下进行了更改,但是通过获得锁来完成读取。同步块内所有对象的状态和所有原始字段的值是否始终具有一致的视图。?

答案仍然是否定的。道理同上。

底线:在同步上下文之外修改值不会确保这些值被刷新到主内存。(因为读取器线程可能在写入器线程之前进入同步块)在synchronized上下文中读取这些值的线程可能最终仍会读取较旧的值,即使它们从主内存中获取这些值。


请注意,这个问题是关于原语的,因此了解 Java为 32 位原语(除了 long 和 double 之外的所有原语)提供了无意义的安全性也很重要,这意味着您可以放心,您至少会看到一个有效值(如果不一致)。

于 2017-02-10T16:52:09.023 回答
1

synchronized所做的只是捕获与其同步的对象的锁。如果锁已经被捕获,它将等待它的释放。它不以任何方式断言该对象的内部字段不会改变。为此,有volatile

于 2017-02-10T15:57:19.907 回答
1

当您在对象监视器上同步时A,可以保证A之后在同一监视器上同步的另一个线程将看到第一个线程对任何对象所做的任何更改。这就是 提供的可见性保证,仅此而已。synchronized

volatile变量保证线程之间的可见性(仅对于变量,volatile并不HashMap意味着映射的内容将是可见的),而不管任何同步块。

于 2017-02-10T16:11:32.967 回答