Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么线程不能正常工作?_Java_Multithreading - Fatal编程技术网

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

Java 为什么线程不能正常工作?,java,multithreading,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)

以下是我的代码:

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呢?我误解了吗?

您的整个
系统.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);
}

首先,您的代码没有正确同步。你的表情

"x is: "+x+"     "+Thread.currentThread().getName()
在不同步的情况下读取共享变量
x
的值,即在数据竞争中。但是,它至少会看到前面的
synchronized
块观察到的值

现在让我们考虑一下程序的可能输出。线程一步一步地进行,所有线程的步骤都是交错的。考虑以下顺序:

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

  • 你可能误解了。@duffymo:你能解释一下我误解了什么吗?其他人做得更好。我没有什么要补充的,只是说,当代码无法满足您的期望时,最好检查您的假设。
    "x is: "+x+"     "+Thread.currentThread().getName()