为什么线程不能正常工作?

时间:2016-10-06 18:21:54

标签: java multithreading

以下是我的以下代码:

class Test {
private int x  = 0;

public void incX() {
    synchronized(this) {
       ++x;                        
    }
    System.out.println("x is: "+x+"     "+Thread.currentThread().getName());
}

public static void main(String[] args) {
    Test test = new Test();             
    Thread t1 = new Thread(() -> {
        test.incX();                    
    });
    Thread t2 = new Thread(() -> {
        test.incX();                   
    });
    t1.start();
    t2.start();

    System.out.println("Done");
}
}

这是我的输出:

x is: 2     Thread-1
x is: 1     Thread-0

此处线程t2输出2,但线程t1也应输出2,对吧?当x等于2时,它应该对线程t1可见,对吧?那么为什么线程t1是1?

线程t2输出2然后线程t1输出1怎么可能?由于线程t2已输出2,因此x的值应为2.那么线程t1如何仍能输出1?我误解了吗?

2 个答案:

答案 0 :(得分:3)

您的整个System.out.println行与原子相距甚远 例如,在字符串的构造和System.out.println的调用之间,可能会发生很多事情。

让我们考虑一个等效的代码块:

public void incX() {
    synchronized(this) {
       ++x;                        
    }
    String implicit = "x is: " + x + "     " + Thread.currentThread().getName();
    // <-- "Point X"
    System.out.println(implicit);
}

现在情况可以是这样的:

  • 线程1启动并继续直到它到达“Point X”,构造了一个字符串,其中包含:
      

    x是:1 Thread-0

  • 线程2启动并继续直到它到达“点X”,构造了一个字符串,其中显示:
      

    x是:2 Thread-1

  • 线程2调用System.out.println,使得总输出到目前为止:
      

    x是:2 Thread-1

  • 线程1调用System.out.println,进行总体输出:
      

    x是:2 Thread-1   x是:1 Thread-0

x的值复制到synchronized块中的另一个变量应足以使行为符合您的期望:

public void incX() {
    int val;
    synchronized(this) {
       val = ++x;                        
    }
    System.out.println("x is: " + val + "     " + Thread.currentThread().getName());
}

答案 1 :(得分:3)

首先,您的代码未正确同步。你的表达

"x is: "+x+"     "+Thread.currentThread().getName()

在没有同步的情况下读取共享变量x的值,即在数据争用中。但是,它至少会看到前面的synchronized块观察到的值。

现在让我们考虑您的计划的可能输出。线程逐步进行,并且所有线程的步骤都是交错的。请考虑以下顺序:

  1. Thread-0输入synchronized块,读取x == 0,将其更新为1,然后离开该块。后续字符串表达式读取此值1
  2. Thread-1输入synchronized块,读取x == 1,将其更新为2,然后离开该块。后续字符串表达式读取此值2
  3. Thread-1输入synchronized方法println并输出结果2
  4. Thread-0输入synchronized方法println并输出结果1.