如果我们正在同步读取,我们是否需要同步写入? [英] Do we need to synchronize writes if we are synchronizing reads?

查看:135
本文介绍了如果我们正在同步读取,我们是否需要同步写入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对同步块几乎没有疑问。
在我提出问题之前,我想与其他相关帖子回答相关问题的链接分享答案。我从同一个答案中引用 Peter Lawrey

I have few doubts about synchronized blocks. Before my questions I would like to share the answers from another related post Link for Answer to related question. I quote Peter Lawrey from the same answer.



synchronized确保您拥有一致的数据视图。这意味着您将读取最新值,其他缓存将获得
最新值。缓存很聪明,可以通过
特殊总线相互通信(不是JLS要求的,但允许的话)这个
总线意味着它不需要触摸主内存来获得
一致视图。

synchronized ensures you have a consistent view of the data. This means you will read the latest value and other caches will get the latest value. Caches are smart enough to talk to each other via a special bus (not something required by the JLS, but allowed) This bus means that it doesn't have to touch main memory to get a consistent view.



  • 如果只使用synchronized,则不需要volatile 。如果你有一个非常简单的操作,那么Volatile是有用的,同步的
    就是矫枉过正。

    If you only use synchronized, you wouldn't need volatile. Volatile is useful if you have a very simple operation for which synchronized would be overkill.


  • 关于上述问题,我有以下三个问题:

    In reference to above I have three questions below :

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

    Q1. Suppose in a multi threaded application there is an object or a primitive instance field being only read in a synchronized block (write may be happening in some other method without synchronization). Also Synchronized block is defined upon some other Object. Does declaring it volatile (even if it is read inside Synchronized block only) makes any sense ?

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

    Q2. I understand the value of the states of the object upon which Synchronization has been done is consistent. I am not sure for the state of other objects and primitive fields being read in side the Synchronized block. Suppose changes are made without obtaining a lock but reading is done by obtaining a lock. Does state of all the objects and value of all primitive fields inside a Synchronized block will have consistent view always. ?

    Q3。 [更新] 无论我们锁定什么,是否会在主内存中读取同步块中读取的所有字段? [CKing回答]

    Q3. [Update] : Will all fields being read in a synchronized block will be read from main memory regardless of what we lock on ? [answered by CKing]

    我已为上述问题准备了参考代码。

    I have a prepared a reference code for my questions above.

    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;
      }
    }
    


    推荐答案

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

    The first thing you need to understand is that there is a subtle difference between the scenario being discussed in the linked answer and the scenario you are talking about. You speak about modifying a value without synchronization whereas all values are modified within a synchronized context in the linked answer. With this understanding in mind, let's address your questions :


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

    Q1. Suppose in a multi threaded application there is an object or a primitive instance field being only read in a synchronized block (write may be happening in some other method without synchronization). Also Synchronized block is defined upon some other Object. Does declaring it volatile (even if it is read inside Synchronized block only) makes any sense ?

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

    Yes it does make sense to declare the field as volatile. Since the write is not happening in a synchronized context, there is no guarantee that the writing thread will flush the newly updated value to main memory. The reading thread may still see inconsistent values because of this.


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

    Suppose changes are made without obtaining a lock but reading is done by obtaining a lock. Does state of all the objects and value of all primitive fields inside a Synchronized block will have consistent view always. ?

    答案仍然是否定的。推理与上述相同。

    The answer is still no. The reasoning is the same as above.

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

    Bottom line : Modifying values outside synchronized context will not ensure that these values get flushed to main memory. (as the reader thread may enter the synchronized block before the writer thread does) Threads that read these values in a synchronized context may still end up reading older values even if they get these values from the main memory.

    请注意,这个问题涉及原语,因此了解Java提供的内容也很重要em>对于32位基元(除了long和double之外的所有基元)的超薄空中安全性,这意味着您可以确保您至少看到有效值(如果不一致)。

    Note that this question talks about primitives so it is also important to understand that Java provides Out-of-thin-air safety for 32-bit primitives (all primitives except long and double) which means that you can be assured that you will atleast see a valid value (if not consistent).

    这篇关于如果我们正在同步读取,我们是否需要同步写入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆