我正在尝试学习 Java 中的并发性,但无论我做什么,2 个线程串行运行,而不是并行运行,因此我无法复制教程中解释的常见并发问题(例如线程干扰和内存一致性错误)。示例代码:
public class Synchronization {
static int v;
public static void main(String[] args) {
Runnable r0 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v++;
System.out.println(v);
}
};
Runnable r1 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v--;
System.out.println(v);
}
};
Thread t0 = new Thread(r0);
Thread t1 = new Thread(r1);
t0.start();
t1.start();
}
这总是给我一个从 1 开始到 0 结束的结果(无论循环长度是多少)。例如,上面的代码每次都给我:
1 2个 3个 4个 5个 6个 7 8个 9 10 9 8个 7 6个 5个 4个 3个 2个 1个 0
有的时候,第二个线程先启动,结果一样但是都是负的,所以还是串行运行。
在 Intellij 和 Eclipse 中尝试过,结果相同。如果重要的话,CPU 有 2 个内核。
更新:它终于可以通过巨大的循环(从 1_000_000 开始)重现,但仍然不是每次都如此,而且最终的差异很小。似乎也使循环中的操作“更重”,例如打印线程名称也使其更可重现。手动向线程添加 sleep 也可以,但是可以这么说,它会使实验变得不那么干净。原因似乎不是第一个循环在第二个循环开始之前完成,因为我看到两个循环都打印到控制台,同时继续运行并且最后仍然给我 0 。原因似乎更像是同一变量的线程竞争。我会深入研究,谢谢。
最佳答案
似乎第一个启动的线程从来没有机会在 Thread Race 中让第二个线程使用变量/第二个线程甚至从来没有时间启动(不能肯定地说),所以第二个几乎*总是等到第一个循环结束。
一些繁重的操作会混合结果:
TimeUnit.MILLISECONDS.sleep(100);
*这并不总是正确的,但你在考试中很幸运
关于java - 线程串行运行而不是并行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52308047/