Java 为什么这里的主线程不等待t2?这里的输出总是超过20000,但并不一致
这里的输出总是>20000,代码等待两个线程完成,4000++语句将被执行 但是您需要了解线程是如何工作的,它们的变量访问是如何工作的,什么是易失性变量和非易失性变量,同步是如何工作的,为什么它们不同,以及为什么您看到的结果是完全合理和100%预期的Java 为什么这里的主线程不等待t2?这里的输出总是超过20000,但并不一致,java,multithreading,Java,Multithreading,这里的输出总是>20000,代码等待两个线程完成,4000++语句将被执行 但是您需要了解线程是如何工作的,它们的变量访问是如何工作的,什么是易失性变量和非易失性变量,同步是如何工作的,为什么它们不同,以及为什么您看到的结果是完全合理和100%预期的 x++基本上是x=x+1这不是一个精确的解释,但这里发生的一般情况=>如果两个线程同时运行该语句,那么您将丢失一个增量,因为两个线程都读取x=123,两个线程都调用123+1=>124,然后都将124分配给x=>调用了两个增量,但值只增加了一个。代
x++基本上是x=x+1这不是一个精确的解释,但这里发生的一般情况=>如果两个线程同时运行该语句,那么您将丢失一个增量,因为两个线程都读取x=123,两个线程都调用123+1=>124,然后都将124分配给x=>调用了两个增量,但值只增加了一个。代码等待两个线程完成,将执行4000++语句
package org.multithreading.basics;
public class ThreadJoin {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(counter);
Thread t2 = new Thread(counter);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Numbers counted =" + counter.getCount());
}
}
class Counter implements Runnable {
private int count;
@Override
public void run() {
for (int i = 0; i < 20000; i++) {
count++;
}
}
public int getCount() {
return count;
}
}
但是您需要了解线程是如何工作的,它们的变量访问是如何工作的,什么是易失性变量和非易失性变量,同步是如何工作的,为什么它们不同,以及为什么您看到的结果是完全合理和100%预期的
x++基本上是x=x+1这不是一个精确的解释,但这里发生的一般情况=>如果两个线程同时运行该语句,您将丢失一个增量,因为两个线程都读取x=123,都调用123+1=>124,然后都将124分配给x=>调用了两个增量,但值只增加了一个
package org.multithreading.basics;
public class ThreadJoin {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(counter);
Thread t2 = new Thread(counter);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Numbers counted =" + counter.getCount());
}
}
class Counter implements Runnable {
private int count;
@Override
public void run() {
for (int i = 0; i < 20000; i++) {
count++;
}
}
public int getCount() {
return count;
}
}
这里计数器是作为两个线程的引用传递的公共对象
Counter counter = new Counter();
两个线程一起工作时,count变量将递增
因此,假设主线程等待t1的计数略高于20000,并在不等待t2完成的情况下终止
事实上,主线程会等待两个线程的增量计数刚好超过20000
上面的解释是针对未等待t2的主线程的
计数是以非同步方式访问的。
表达式count++等效于count=count+1
两个操作赋值和加法并行完成。因此,t1增加的值可能会被t2覆盖。在执行过程中,此值将不按顺序且不是常量。因此,计数的每次值都会发生变化
这里计数器是作为两个线程的引用传递的公共对象
Counter counter = new Counter();
两个线程一起工作时,count变量将递增
因此,假设主线程等待t1的计数略高于20000,并在不等待t2完成的情况下终止
事实上,主线程会等待两个线程的增量计数刚好超过20000
上面的解释是针对未等待t2的主线程的
计数是以非同步方式访问的。
表达式count++等效于count=count+1
两个操作赋值和加法并行完成。因此,t1增加的值可能会被t2覆盖。在执行过程中,此值将不按顺序且不是常量。因此,计数的每个时间值都会发生变化。根据上述代码,我们同时调用了t1.start和t2.start,所以,两个线程都将开始执行在run方法中定义的任务,但在下一行中我们调用了t1.join,因此主线程将等待t1方法的完成,但t2线程仍在并行执行。两个线程都在读取相同的计数值,并同时更新它,因此它实际上增加了一次,而不是一次增加两次调用t2.join,然后主线程将等待t2线程的完成,因此我们可以看到范围为>20000和的输出。根据上述代码,我们同时调用了t1.start和t2.start,两个线程都将开始执行在run方法中定义的任务,但在下一行中我们调用了t1.join,因此主线程将等待t1方法的完成,但t2线程仍在并行执行。两个线程都在读取相同的计数值,并同时更新它,因此它实际上增加了一次,而不是一次增加两次调用t2.join后,主线程将等待t2线程的完成,因此我们可以看到输出范围>20000,实际上,主线程将等待两个线程的增量计数刚好超过20000。主线程不关心计数。如果一个线程的太多操作被另一个线程的一个操作覆盖,最终结果甚至可能小于20000。解释是为什么这里的主线程不等待t2?事实上,主线程会等待两个线程的增量计数刚好超过20000。,主线程不关心计数。如果一个线程的太多操作被另一个线程的一个操作覆盖,最终结果可能会少于20000。解释是为什么这里的主线程不等待t2?非常感谢!我忽略了两个线程可以同时执行增量步骤的想法 太多了!我忽略了两个线程可以同时执行增量步骤的想法。