【问题标题】:Volatile and Synchronized易失和同步
【发布时间】:2016-04-04 07:41:54
【问题描述】:

关于同步和易失性,我还不太了解。

我了解线程可以在本地保护更改。从我目前所读到的是同步>易失性。

假设我有一个不是 long 或 double 的参数,所以基本上是一个标准 Integer(非原子)。

我有一个同步的方法,我用这个整数做了很多工作。 所有线程都会得到这个 Integer 的更新版本吗?还是我也必须将其声明为 volatile?

public class stackoverflow {

    private int x = 0;

    public synchronized void rechnen(){ 
        //dosomething   
    }
}

基本上在 rechnen() 完成后,我得到了 10000 个线程,因为我的方法是同步的,都会得到 x 的更新版本吗?还是我也必须将其声明为 volatile?

【问题讨论】:

  • 请用您使用的编程语言标记您的问题。

标签: java multithreading synchronized volatile


【解决方案1】:

是的,他们将获得更新版本。 synchronized 保证两件事:变化的可见性和原子性。 volatile 只是保证更改的可见性。 Java 保证同步块内的代码不会被优化(通过在 synchronized 块内外混合命令),因此在同步块结束后对其中变量的每次更改都将对所有线程可见。

【讨论】:

  • “在同步块结束后,其中变量的每一个更改都将对所有线程可见”这当然是正确的,但是,我认为这是不正确的“Java保证同步块内的代码不会被优化”。
  • @v.ladynev 是的,你是对的。我写的不是很好。我编辑了答案。我在想的是Java不会通过在synchronized块内外混合语句来优化代码。
  • ...其中变量的每一个变化,在同步块结束后对所有线程都是可见的。 不完全正确。 JLS 只保证如果线程 A 更新一个变量然后退出一个同步块,那么线程 B 将能够在线程 B 在同一个对象上同步之后看到更新。
【解决方案2】:

@partlov 已经回答了您的问题,因此作为旁注,您可能还需要考虑其他一些事情。

不要使用 synchronized 作为修饰符

当将方法声明为同步时,它使用监视器。在 Java 中,每个 Object 恰好是一个监视器,在这种情况下使用类实例。所以你的例子有效地变成了:

public void rechnen(){ 
    synchronized(this) {
        //dosomething
    }   
}

现在这会带来一个潜在的问题,因为您的显示器正在泄漏。应用程序的其他部分可以使用相同的监视器来同步完全不相关的代码,这可能会导致/导致性能下降,或者更糟糕的是,当它相关时,可能会导致意外死锁。

因此,主要的建议是,始终将您的显示器保密。所以像:

public class stackoverflow {
    private final Object monitor = new Object();
    private int x = 0;

    public void rechnen(){
         synchronized(monitor) {
            //dosomething
         } 
    }
}

了解您的 API

volatilesynchronized 之间有大量用于特定并发目的的工具。其中大部分混合使用volatilesynchronizedCAS-operations。例如,AtomicInteger 为您提供原子整数运算,且竞争少得多,正如 synchronized 所见。所以试着真正熟悉java.util.concurrent

【讨论】:

    【解决方案3】:

    是的,他们将获得更新的版本,但前提是他们自己输入了同步块。如果他们没有在同一个对象上输入同步块(锁定同一个监视器),则不能保证他们会看到更新。

    如果不希望其他线程进入同步块,则必须将该变量声明为 volatile。

    【讨论】:

    • 不必是同一个同步块。它确实必须是在同一个锁对象上同步的块。
    【解决方案4】:

    声明私有 volatile int x = 0;它将为您服务。为了更好地理解,请参阅 AtomicInteger 的实现。

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 2021-10-24
      • 2017-08-14
      • 2014-07-03
      • 2016-07-02
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多