通过两个不同的线程设置和访问varibale

时间:2016-09-23 21:15:39

标签: java multithreading

我有两个线程,一个设置类的变量,另一个通过get方法访问变量。

public class Parent {
    private int value = -1

    public int getValue()
      return this.value;
    }

    public void setValue(int value){
      this.value = value;
    }

    private class UpdatingVaribale extends Thread {

    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        try {
            setValue(2);
            Thread.currentThread().interrupt();
        }
      } 
    }
}

private class GettingVaribale extends Thread {

    public void run() {
      while (getValue == -1) {
        try{
            System.out.println(getValue);
            Thread.sleep(500);
         } catch (InterruptedException e) {
         }
       }
       System.out.println(getValue); 
    }
}

问题是第二个线程中while循环的条件总是trueSystem.out.println(getValue)始终打印-1。我想知道为什么第二个线程没有得到value的新值2。我不认为synchronized在这里很重要,因为一个线程正在设置变量而另一个线程只是访问变量。

1 个答案:

答案 0 :(得分:2)

这里有一些解决方案:

  1. 使用标准Java类AtomicInteger以多线程安全方式存储您的值。实际上,这是最好,最快的方式。
  2. synchronized关键字添加到您的getValuesetValue方法
  3. volatile java关键字添加到i字段定义
  4. 您的问题的根源是i变量值实际上在不同的线程中看起来不同导致CPU速度和内存优化,您必须指定JVM以某种方式不执行此优化并且 - 相反 - 使最新所有主题中都可以看到i值。

    更新测试代码

    public class SyncProblem {
    
        public static void main(String[] args) {
            Parent parent = new Parent();
            new Thread(parent.new GettingVaribale()).start();
            new Thread(parent.new UpdatingVaribale()).start();
        }
    }
    
    class Parent {
        private volatile int value = -1;
    
        public int getValue() {
            return this.value;
        }
    
        public void setValue(int value) {
            this.value = value;
        }
    
        class UpdatingVaribale implements Runnable {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    setValue(2);
                    Thread.currentThread().interrupt();
                }
            }
        }
    
        class GettingVaribale implements Runnable {
            @Override
            public void run() {
                while (getValue() == -1) {
                    try {
                        System.out.println(getValue());
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                    }
                }
                System.out.println(getValue());
            }
        }
    }