当前位置: 首页 > 面试题库 >

如果我们正在同步读取,是否需要同步写入?

秦涵映
2023-03-14
问题内容

我对同步块几乎没有疑问。
1. > 同步可确保您拥有一致的数据视图。这意味着您将读取最新值,而其他缓存将获得最新值。高速缓存足够智能,可以通过特殊总线相互通信(这不是JLS所必需的,但允许)。该总线意味着不必触摸主内存即可获得一致的视图。

  1. 如果仅使用同步,则不需要volatile。如果您有一个非常简单的操作(对于同步操作可能会过分杀伤),则波动性很有用。

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

Q1。假设在多线程应用程序中,仅在同步块中读取了对象或原始实例字段(写操作可能会在其他方法中发生而没有同步)。同样,在其他对象上定义了同步块。
声明它为易失性(即使仅在Synchronized块中读取)是否有意义

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

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

问题答案:

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

Q1。假设在多线程应用程序中,仅在同步块中读取了对象或原始实例字段(写操作可能会在其他方法中发生而没有同步)。同样,在其他对象上定义了同步块。声明它为易失性(即使仅在Synchronized块中读取)是否有意义?

是的,将字段声明为确实有意义volatile。由于写操作不是在synchronized上下文中进行的,因此无法保证写线程会将新更新的值刷新到主内存中。因此,读取线程可能仍会看到不一致的值。

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

答案是否定的。推理与上面相同。

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

请注意,这个问题是关于基元的,因此理解Java 为32位基元(除long和double以外的所有基元)提供 超薄安全性
也很重要,这意味着您可以放心,至少有效值(如果不一致)。



 类似资料:
  • 我对同步块有一些疑问。在提问之前,我想分享另一个相关帖子链接的答案,以回答相关问题。我引用彼得·劳里的同一个答案。 > <块引号> 同步确保您对数据有一致的视图。这意味着您将读取最新值,其他缓存将获得最新值。缓存足够智能,可以通过特殊总线相互通信(JLS不需要,但允许)该总线意味着它不必触摸主存储器即可获得一致的视图。 如果您只使用同步,则不需要Volatile。如果您有一个非常简单的操作,而同步

  • 问题内容: 我有两个线程,我想确保我在LinkedBlockingQueue上正确进行了同步。这正确吗?还是不需要在(messageToCommsQueue)上进行显式同步? 宣言: 方法一: 方法二: 问题答案: 是的,没有必要。JavaDoc说: BlockingQueue实现是线程安全的。

  • 问题内容: 这样做,即ConcurrentHashMap(所有非retreival操作,等)需要在被包裹块?我知道所有这些操作都是线程安全的,因此这样做有真正的好处/需要吗?使用的唯一操作是和。 问题答案: 不,这样做会失去您的利益。您也可以使用with 或锁定整个表(这是在中包装操作时要执行的操作,因为隐含的监视器是整个对象实例。) 目的是通过允许在表上进行并发读/写而不锁定整个表来提高并发代码

  • 如何写这个问题?老实说,我不明白这个问题的意思。A) 编写读者和作者优先于读者的解决方案,并评论每个信号量的功能。(记住变量和信号量的定义和初始化)B)读卡器的优先级意味着什么?当一个作家在写作时,到达的读者会发生什么?当编写器结束其操作时会发生什么?

  • 问题内容: 说我有一个全局对象: 有一个线程定期运行以从远程获取新编号并更新(仅写入): 并且有一个或多个线程随机使用此全局变量(仅读取): 您可以看到我不使用任何锁或对其进行保护,对吗?是否有可能引起问题的潜在问题? 更新: 就我而言,读取线程必须实时获取最新的值并不是很重要。我的意思是,如果有任何问题(由于缺少锁定/同步而导致)使一个读取线程错过了该值,那就没关系了,因为它将有机会尽快运行相同

  • 您可以通过 Bluetooth 连接,以无线方式,将数据从手表传输至 Polar Flow 应用程式。或者您可以使用 USB 端口和 FlowSync 软件,将手表与 Polar Flow 网络服务同步。若要在手表与 Flow 应用程式之间同步数据,您需要拥有 Polar 账户。如果您想将手表上的数据直接同步到网络服务,除了 Polar 账户,您还需要 FlowSync 软件。如果您已设置手表,已