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 线程意外操纵的变量 公共类主{ 静态int i=0; 公共静态void main(字符串[]args){ 对于(;iSystem.out.println(i)).start(); } }_Java_Multithreading_Concurrency - Fatal编程技术网

Java 线程意外操纵的变量 公共类主{ 静态int i=0; 公共静态void main(字符串[]args){ 对于(;iSystem.out.println(i)).start(); } }

Java 线程意外操纵的变量 公共类主{ 静态int i=0; 公共静态void main(字符串[]args){ 对于(;iSystem.out.println(i)).start(); } },java,multithreading,concurrency,Java,Multithreading,Concurrency,我希望上面的代码也能打印出来 0 一, 或 1 0 但令我惊讶的是,我得到了 2 二, 我运行同样的程序,它也给我同样的结果。但是如果你像那样运行它 public class Main { static int i = 0; public static void main(String[] args) { for (; i < 2; i++) new Thread(() -> System.out.println(i)).st

我希望上面的代码也能打印出来

0
一,

1
0

但令我惊讶的是,我得到了

2
二,


我运行同样的程序,它也给我同样的结果。但是如果你像那样运行它

public class Main {
    static int i = 0;

    public static void main(String[] args) {
        for (; i < 2; i++)
            new Thread(() -> System.out.println(i)).start();
    }
}
(;i<2;i++)的
{
睡眠(10);
新线程(()->System.out.println(i)).start();
}
结果变成

1
二,

如果在
新线程(()->System.out.println(i)).start()下面添加
Thread.sleep(10)
它输出

0
一,

这是因为当前线程(main)在线程之前执行循环

  • 主线程启动
  • 循环开始
  • 线程-1已创建。(线程仍处于空闲状态)
  • 循环连续。(i=1)
  • 线程-2已创建。(线程处于空闲状态)
  • 循环结束
  • 主线程结束

  • 线程1和线程2在代码的第2步和第7步之间开始。操作系统处理线程调度,因此您无法在该程序中预期结果。

    我运行相同的程序,它也为我提供相同的结果。但是如果你像那样运行它

    public class Main {
        static int i = 0;
    
        public static void main(String[] args) {
            for (; i < 2; i++)
                new Thread(() -> System.out.println(i)).start();
        }
    }
    
    (;i<2;i++)的
    {
    睡眠(10);
    新线程(()->System.out.println(i)).start();
    }
    
    结果变成

    1
    二,

    如果在
    新线程(()->System.out.println(i)).start()下面添加
    Thread.sleep(10)
    它输出

    0
    一,

    这是因为当前线程(main)在线程之前执行循环

  • 主线程启动
  • 循环开始
  • 线程-1已创建。(线程仍处于空闲状态)
  • 循环连续。(i=1)
  • 线程-2已创建。(线程处于空闲状态)
  • 循环结束
  • 主线程结束

  • 线程1和线程2在代码的第2步和第7步之间开始。操作系统处理线程调度,因此您无法在此程序中预期结果。

    结果因调度程序而异。无法预测它总是
    2,2
    。见下图。最终可能会得到不同的值。这是因为操作系统有自己处理线程的方式。您可以阅读更多关于线程的信息-----------------------------------------------------------------------------------------------图像显示eclipse输出。

    结果因调度程序而异。无法预测它总是
    2,2
    。见下图。最终可能会得到不同的值。这是因为操作系统有自己处理线程的方式。您可以阅读更多关于线程的信息--------------------------------------------------------------------------------------------这些图像显示eclipse输出。

    当您在类
    Main
    的主体中引用
    i
    时,您真正要做的是引用静态变量
    Main.i
    (编译器很有礼貌,不会让您键入完整路径)
    Main.i
    可以从静态上下文进行计算。因此,如果lambda被去除到该方法中

    for (; i < 2; i++) {
        Thread.sleep(10);
        new Thread(() -> System.out.println(i)).start();
    }
    

    现在应该更清楚的是,有多个线程竞相访问共享(可变!)变量
    Main.i
    ;主线程正在更新它,而创建的线程正在读取它。因为新线程中的读取是快速的,所以您无法保证打印出什么。

    当您在类
    Main
    的主体中引用
    i
    时,您真正做的是引用静态变量
    Main.i
    (编译器很礼貌,不会让您键入完整路径。)本例中的lambda没有捕获任何东西
    Main.i
    可以从静态上下文进行计算。因此,如果lambda被去除到该方法中

    for (; i < 2; i++) {
        Thread.sleep(10);
        new Thread(() -> System.out.println(i)).start();
    }
    

    现在应该更清楚的是,有多个线程竞相访问共享(可变!)变量
    Main.i
    ;主线程正在更新它,而创建的线程正在读取它。由于新线程中的读取是快速的,因此无法保证打印出来的内容。

    有一个dupe(不是完美的,但是)解释了当访问lambda时(这里由线程本身)将对lambda进行评估,
    i
    在线程实际启动之前已经是“2”(在某些情况下也可以是“1”)。这一切都取决于调度程序。有一个dupe(不是完美的,但是)解释了当访问lambda时(这里由线程本身)将对lambda进行评估,
    i
    在线程实际启动之前已经是“2”(在某些情况下也可以是“1”)。这完全取决于调度程序。啊,我错过了第二部分,你移动了
    线程。sleep
    。没关系:)。啊,我错过了你移动
    线程的第二部分。sleep
    。没关系:)。嗨,布莱恩,非常感谢你向我解释了这么简单的事情。我需要再看一次你的书。嗨,布莱恩,非常感谢你向我解释了这么一点基本的事情。我需要把你的书再读一遍。