【问题标题】:volatile keyword doesnt synchronize the valuesvolatile关键字不同步值
【发布时间】:2018-02-09 08:12:57
【问题描述】:

下面的代码给我的结果如下:

Change listener
Change listener
Change listener
Incrementing MY_INT to:1
Incrementing MY_INT to:2
Got Change for MY_INT :1loc:0
Change listener
Change listener
Change listener
Change listener
Change listener
Change listener
Change listener
Change listener
Change listener
Incrementing MY_INT to:3
Change listener
Incrementing MY_INT to:4
Incrementing MY_INT to:5
Got Change for MY_INT :3loc:2
Change listener

我的问题是,由于我使用了 volatile,MY_INT 值应该反映为 4 或 5。为什么它没有反映。有时,即使是这个值,我们也会得到 1。请有人让我知道我哪里出错了。

public class VolatileTest {
    private static volatile int MY_INT = 0;

    public static void main(String[] args) {
        new ChangeListener().start();
        new ChangeMaker().start();
    }

    static class ChangeListener extends Thread {
        @Override
        public void run() {
            int local_value = MY_INT;
            while ( local_value < 5){
                if( local_value!= MY_INT){
                   System.out.println("Got Change for MY_INT :"+ MY_INT+"loc:"+local_value);
                     local_value= MY_INT;
                }
 System.out.println("Change listener");
            }
        }
    }

    static class ChangeMaker extends Thread{
        @Override
        public void run() {

            int local_value = MY_INT;
            while (MY_INT <5){
                 System.out.println("Incrementing MY_INT to:"+(local_value+1));
                MY_INT = ++local_value;

            }
        }
    }
}

【问题讨论】:

  • 'volatile 关键字不同步值' - 是的,而且它不会以某种方式强制您的两个线程以任何保证的顺序发出输出。

标签: multithreading synchronized volatile


【解决方案1】:

这是可能发生的一件事:

 ChangeMaker                     ChangeListener
  ...                             ...
  MY_INT = 3
                                 Sees MY_INT != 2, calls println(...)
  MY_INT = 4
  MY_INT = 5
                                 local_value = MY_INT;    // 5
  all done (MY_INT==5)           all done (MY_INT==5)

更改侦听器可能会错过查看更改,因为测试 local_value!=MY_INT 与分配 local_value=MY_INT; 不是原子的

【讨论】:

    【解决方案2】:

    除了一件事之外,您做得很好,您在访问 volatile 变量时没有添加同步。与原子 volatile 变量不同,它保证您获得实际值但不会改变。我想在你的情况下最好使用原子作为AtomicInteger。您也可以将您的 int 更改为 Integer 在您的代码中添加额外的 synchronized,如下例所示。

    public class VolatileTest {
    private static volatile Integer MY_INT = 0;
    
    public static void main(String[] args) {
        new ChangeListener().start();
        new ChangeMaker().start();
    }
    
    static class ChangeListener extends Thread {
        @Override
        public void run() {
            int local_value = MY_INT;
            while (local_value < 5) {
                // ! Here
                synchronized (MY_INT) {
                    if (local_value != MY_INT) {
                        System.out.println("Got Change for MY_INT :" + MY_INT + "loc:" + local_value);
                        local_value = MY_INT;
                    }
                }
                System.out.println("Change listener");
            }
        }
    }
    
    static class ChangeMaker extends Thread {
        @Override
        public void run() {
    
            int local_value = MY_INT;
            while (MY_INT < 5) {
                System.out.println("Incrementing MY_INT to:" + (local_value + 1));
                // ! And here
                synchronized (MY_INT) {
                    MY_INT = ++local_value;
                }
            }
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2022-12-19
      • 1970-01-01
      • 2021-10-26
      相关资源
      最近更新 更多