Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.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_Synchronization - Fatal编程技术网

Java 为什么我在同步方面有问题?

Java 为什么我在同步方面有问题?,java,multithreading,synchronization,Java,Multithreading,Synchronization,为什么名为“count”的变量最终不等于20000 public class Main { private Integer count = 0; public void increment() { synchronized (count) { count++; } } public static void main(String[] args) { Main app = new Main(); app.doWork(); } public v

为什么名为“count”的变量最终不等于20000

public class Main {
private Integer count = 0;

public void increment() {
    synchronized (count) {
        count++;
    }
}

public static void main(String[] args) {
    Main app = new Main();
    app.doWork();
}

public void doWork() {

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i=0; i<10000; i++) {
                increment();
            }
        }
    });

    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i=0; i<10000; i++) {
                increment();
            }
        }
    });

    t1.start();
    t2.start();
    System.out.println(count);
}
公共类主{
私有整数计数=0;
公共空间增量(){
已同步(计数){
计数++;
}
}
公共静态void main(字符串[]args){
主应用程序=新主应用程序();
app.doWork();
}
公共工作{
线程t1=新线程(新的可运行线程(){
@凌驾
公开募捐{

对于(int i=0;i,因为
start
创建了一个新线程,当您打印计数时,您不确定线程执行是否完成

t1.start();
t2.start();

System.out.println(count); // Here you don't know if t1 and t2 ended their execution
加入线程以等待它们完成任务:

t1.start();
t2.start();

t1.join(); // wait for t1 to finish
t2.join(); // wait for t2 to finish

System.out.println(count); // 20000

注意:您必须在
join
调用上处理
InterruptedException

因为
start
创建了一个新线程,当您打印计数时,您不确定线程执行是否完成

t1.start();
t2.start();

System.out.println(count); // Here you don't know if t1 and t2 ended their execution
加入线程以等待它们完成任务:

t1.start();
t2.start();

t1.join(); // wait for t1 to finish
t2.join(); // wait for t2 to finish

System.out.println(count); // 20000

注意:您必须在
join
调用上处理
InterruptedException

您在
count
上同步。但是您的代码更改
count
。在不同对象上同步的不同线程不能保证原子性

使用单独的
final
监视器对象进行同步

另请参见@backslax的答案,以确保打印正确的最终结果

编辑

他的答案可以归结为:如果您在不等待线程在主线程上完成的情况下打印结果,您将看到一些中间结果,甚至可能是0


因此,在打印最终结果之前,您需要在两个线程上调用
join()
,直到线程完成为止。

您在
count
上同步。但是您的代码会更改
count
。在不同对象上同步的不同线程不能保证原子性

使用单独的
final
监视器对象进行同步

另请参见@backslax的答案,以确保打印正确的最终结果

编辑

他的答案可以归结为:如果您在不等待线程在主线程上完成的情况下打印结果,您将看到一些中间结果,甚至可能是0


因此,在打印最终结果之前,需要在两个线程上调用
join()
,直到线程完成为止。

只有一个“计数” object@Mickcount是一个
Integer
对象-由于
Integer
对象是不可变的,所以对于count@Mick只有一个count引用,每次增加后,它都指向不同的对象。噢!谢谢你的解释。它完全忽略了“count++”正在创建一个新对象。@Gray根据请求编辑了我的答案这里只有一个“计数” object@Mickcount是一个
Integer
对象-由于
Integer
对象是不可变的,所以对于count@Mick只有一个count引用,每次增加后,它都指向不同的对象。噢!谢谢你的解释。它完全忽略了“count++”正在创建一个新对象。@Gray编辑了我的答案,正如你最后的问题所要求的那样,请阅读jcip。至于你最后的问题,请阅读jcip。谢谢你的回答,但在我看来,@bowmore在这一点上是正确的situation@PavelPavel不是。你的问题是“为什么名为‘count’的变量最终不等于20000?”答案是“因为你没有等待线程终止”。鲍莫尔,为了回答这个特定的问题,告诉你阅读我的答案。是的。我已经犯了两个错误谢谢你的回答,但在我看来,@bowmore在这个问题上是正确的situation@PavelPavel不是。你的问题是“为什么名为‘count’的变量最终不等于20000?”?答案是“因为你没有等待线程终止”。bowmore,为了回答这个问题,告诉你阅读我的答案。是的,我犯了两个错误