gpt4 book ai didi

使用 join() 的 Java 多线程程序在计算相邻数字之和时给出了错误的结果

转载 作者:搜寻专家 更新时间:2023-10-31 19:52:01 24 4
gpt4 key购买 nike

我编写了这个简单的多线程程序来将 1 到 100,000 之间的数字相加。当我运行这个时,我得到了不同的值作为最终结果(值小于预期的 5000050000 )。当我只使用一个线程执行程序时,它给出了正确的结果。程序也适用于较小的值,例如 100。可能出了什么问题?提前致谢。

class Calculation {

private long total=0;
public void calcSum(long start, long end) {
long i = start;
for( ;i<=end; i++) {
total += i;
}
}
public long getTotal() {
return total;
}
}

class CalculatorThread extends Thread{
private long start;
private long end;
private Calculation calc;
public CalculatorThread(long start, long end, Calculation calc) {
this.start = start;
this.end = end;
this.calc = calc;
}
@Override
public void run() {
calc.calcSum(start, end);
}
}

public class ParallelTest {

public static void main(String[] args) throws InterruptedException {

int start = 1;
int end = 100000;

Calculation calc = new Calculation();
CalculatorThread ct1 = new CalculatorThread(start, end/2 , calc);
CalculatorThread ct2 = new CalculatorThread( (end/2) + 1, end, calc);

ct1.start();
ct2.start();

ct1.join();
ct2.join();

System.out.println(calc.getTotal());
}
}

最佳答案

对共享可变状态的非同步访问通常不会很顺利。

在您的Calculation calc 中,有一个可变变量long total。当您启动线程时:

  CalculatorThread ct1 = new CalculatorThread(start, end/2 , calc);
CalculatorThread ct2 = new CalculatorThread( (end/2) + 1, end, calc);

您在这两个线程之间共享 calc 的可变状态。 calc 中没有任何同步,因此线程只会在随机时间间隔内互相破坏内存。

这是一个工作版本:

class ParallelSum {
public static long calcSum(long start, long end) {
long total = 0;
for(long i = start; i < end; i++) {
total += i;
}
return total;
}

public static class CalculatorThread extends Thread {
private long result = 0;
private long start;
private long end;
public CalculatorThread(long start, long end) {
this.start = start;
this.end = end;
}
@Override
public void run() {
result = calcSum(start, end);
}
public long getResult() {
return result;
}
}

public static void main(String[] args) throws InterruptedException {
int start = 1;
int end = 100000;
int endExcl = end + 1;

CalculatorThread ct1 = new CalculatorThread(start, endExcl/2);
CalculatorThread ct2 = new CalculatorThread(endExcl / 2, endExcl);

ct1.start();
ct2.start();

ct1.join();
ct2.join();

System.out.println(ct1.getResult() + ct2.getResult());
}
}

输出:

5000050000

附加说明:始终使用 [inclusive, exclusive) 范围索引。这大大降低了差一错误的可能性。此外,我用一个方法替换了 Calculation 类:方法内部的局部变量不会出错,可变状态越少越好。

关于使用 join() 的 Java 多线程程序在计算相邻数字之和时给出了错误的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50556922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com