1

我希望两个线程共享变量,但有时在运行时它会打印两次,而不是 1 和 2。

public class man implements Runnable{

    int value = 0;

    public static void main(String[] args){
        Runnable job = new man();
        Thread work1 = new Thread(job);
        work1.setName("Thread1");
        Thread work2 = new Thread(job);
        work2.setName("Thread2");

        work1.start();
        work2.start();
    }


    public void run(){
        synchronized(this){
            value = value + 1;
        }
        System.out.println("VALUE = " + value +", Running " + Thread.currentThread().getName());
    }



}

有时输出是:

VALUE = 2, Running Thread2
VALUE = 2, Running Thread1

其他时间是:

VALUE = 1, Running Thread2
VALUE = 2, Running Thread1

为什么会这样?我在 HeadFirst 书中学习 Java,出现了这个问题。

4

2 回答 2

3

您需要同步对变量的访问。

发生的事情是两个线程都在增加变量后读取变量的值。换句话说:

  1. 线程 1:syncronized(this) => 线程 2 不能进入它自己的 syncronized(this)
  2. 线程1:值=值+ 1;=> 说 1
  3. 线程 1:结束同步块 => 线程 2 现在可以进入自己的同步(this)
  4. 线程 2: syncronized(this) => 线程 1 不能进入它自己的 syncronized(this)
  5. 线程 2: value= value + 1 ; => 2
  6. 线程2:打印值,即2
  7. 线程1:打印值,即2

解决方案是System.out.println("VALUE = " + value +", ...);synchronized块内移动。这会强制将上述序列重新排序为:

  1. 线程 1:syncronized(this) => 线程 2 不能进入它自己的 syncronized(this)
  2. 线程1:值=值+ 1;=> 说 1
  3. 线程1:打印值,即1
  4. 线程 1:结束同步块 => 线程 2 现在可以进入自己的同步(this)
  5. 线程 2: syncronized(this) => 线程 1 不能进入它自己的 syncronized(this)
  6. 线程 2: value= value + 1 ; => 2
  7. 线程2:打印值,即2
于 2013-09-01T00:00:06.620 回答
3

您没有在System.out.println调用中同步访问,因此有时“第二个”线程会在“第一个线程”打印之前递增。

于 2013-08-31T23:50:42.713 回答