【问题标题】:Java: How to use synchronized and volatileJava:如何使用同步和易失性
【发布时间】:2013-01-12 06:01:04
【问题描述】:

我有两个线程。第一个线程调用 setX 方法,第二个线程调用 getX 方法。尽管我只有一个写作线程,但我是否必须将方法设置为同步?我也可以用第二个类和 volatile 变量来解决我的线程问题吗?

public class Test {
    private int x;  

    public synchronized  void setX(int x) {
        this.x = x;
    }

    public synchronized  int getX() {
        return this.x;
    }
}

public class Test2 {
    private volatile int x; 

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return this.x;
    }
}

【问题讨论】:

    标签: java multithreading synchronized volatile


    【解决方案1】:

    这里不使用synchronized volatile,我个人会使用AtomicInteger

    public class Test {
        private final AtomicInteger x = new AtomicInteger();  
    
        public void setX(int value) {
            x.set(value);
        }
    
        public int getX() {
            return x.get();
        }
    }
    

    (请注意,我还修复了您的 get / set - 之前您的 getX 正在设置,而您的 setX 正在...)

    【讨论】:

    • 但是带volatile的类也是解决办法?
    • @user1720132:我相信是这样,但不太清楚——您需要详细了解 Java 内存模型才能对其进行推理。使用AtomicReference,您想要达到的目标一目了然。
    • 这是独立于实现的,因此更可取。
    • volatile 和 synchronized 也是独立于实现的。我同意 AtomicInteger 是最清晰的解决方案。
    • 关于 get()/set(),Test2 看起来与 AtomicInteger 相同,后者也由私有 volatile int 支持。
    【解决方案2】:

    要回答您的问题,是的,您需要某种形式的同步。由于您的共享状态是单个变量,并且此变量的类型为 int,因此写入将是原子的(如果变量是 long 或 double 则不是这种情况)。但是您仍然需要同步以确保您没有可见性问题:线程 A 可以写入变量,而线程 B 看不到写入的值,而是看到之前的值。

    在这种情况下,可以使用 synchronized、volatile 或 AtomicInteger 来实现同步。所有这些技术都将确保写入对变量的任何后续读取都是可见的。

    【讨论】:

      【解决方案3】:

      Volatile变量只保证变量和顺序的可见性 线程的代码。但它不提供线程设施 方法的所有权。 Synchronized关键字让线程拥有 synchronized 方法的所有权。

      按照您的查询进行:

      第一个线程调用setX方法,第二个线程调用getX 方法。我是否必须设置方法synchronized 虽然我只有一个写作线程?

      取决于你想要什么。如果您希望 Thread2 仅在 Thread1 调用 setX 之后才调用 getX,那么是的,您需要同步这些方法,但是您还必须使用 wait()notify() 方法。

      我也可以解决我的第二课和第二课的线程问题吗? volatile变量?

      同样,这取决于你想要什么。如果您希望您的 Thread2 调用 getX 方法而不关心其他 Thread 调用的 setX 方法,那么您应该使用 volatile 以便 Thread2 可以获取 x 的最新值。

      【讨论】:

        猜你喜欢
        • 2016-04-04
        • 2017-02-17
        • 2021-10-24
        • 2014-07-03
        • 2016-05-31
        • 2012-02-22
        • 1970-01-01
        • 2016-07-02
        • 1970-01-01
        相关资源
        最近更新 更多