java - 线程之间共享数据不正确

标签 java multithreading

我的程序有问题。总和数据在多个线程之间共享。它应该在每个线程添加后给出总和。

public class ThreadPractise implements Runnable
{
    Integer num;
    String name;
    volatile Integer commonSum;
    Object lock;

    public ThreadPractise(Integer i,String threadName ,Integer sum, Object sharedLock) {
        num = i;
        name = threadName;
        commonSum =sum;
        lock = sharedLock;
    }

    @Override
    public void run() {
        Integer cube = calculate(num);
        update(cube);
        System.out.println(Thread.currentThread().getName()+" has commonSum after update as "+commonSum);
    }

    public void update(Integer cube) {
        synchronized (lock) {
            this.commonSum = this.commonSum + cube;
            System.out.println(Thread.currentThread().getName()+" has commonSum as "+commonSum);
        }
    }
    public int calculate(Integer num2) {
        return (num2*num2*num2);
    }

    public static void main(String[] args) {

        Integer sum = new Integer(0);
        Object lock = new Object();
        for(int i=1;i<=3;i++)
        {
            Thread t = new Thread(new ThreadPractise(i, "Thread"+i, sum,lock));
            t.start();
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Sum of 1^3+2^3+3^3 = "+sum);

    }

}

但是总和始终为 0。当我更改为 AtomicInteger 时,它可以工作,但我需要解决此实现的问题。另外请告诉我我所做的线程锁定是否正确。

最佳答案

您的问题与并发无关。查看您的 main 方法。它有一个局部变量sum。该局部变量永远不会更新。相反,您正在更改 ThreadPractise 实例的 num 字段引用的对象。该值使用 sum 的值进行初始化,但一旦替换 num 的值,其值就不再与 sum 相关,因为值只是被替换但不更新。因此,打印的值仍然是 0,它是最初分配给 sum 的值。

简单地说,您所做的就是:

Integer a = 0;
Integer b = a;
b = 1;                 // does not change a
System.out.println(a); // prints '0'

但在 Java 中,如果不为变量分配新值,则无法更改该变量引用的值。

相反,使用AtomicInteger,您将一个可变实例传递给您的线程。您现在不是替换 num 引用的值,而是更新该实例所代表的值。这样,numsum 变量就保持相同,因为它们引用相同的对象。对于不可变Integer来说,这种方法是不可能的。如果 Integer 类有一个类似 setValue(int) 的方法,那么您所做的将与 sumnum 一样工作同样会引用同一个对象。

关于java - 线程之间共享数据不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26968625/

相关文章:

java - 如何使用 Java 线程并行化 ArrayList 操作?

java - 运行 Activity 之间的沟通?

java - 运行 mvn package 时出现 NoClassDefFoundError ArchiverException

javascript - 在 Javascript 中访问对象时自动调用函数

c# - 在这种情况下我应该使用后台 worker 还是计时器?

c# - 变量缓存

Java 用异常处理覆盖 compareTo

java - 如何从具有 gradle 依赖性的代码创建 Android 库?

java - 此操作中有1个数据节点在运行,并且排除了1个节点

C++ 异步运行一个函数而不阻塞用户界面