Java线程求和单值

时间:2013-03-31 15:19:06

标签: java multithreading synchronized addition

在Java中,为什么在synchronized下面的代码中可以发表评论?因为加法几乎是原子的,因此错误或失败的可能性太小了?

public class AddInParallel {

    public static void main(String[] args) {

        class sumValue {
            public int sum = 0;
            sumValue() {}
            public /*synchronized*/ void add(int i) {
                sum += i;
            }
        }

        // final makes sumValue visible to threads
        final sumValue sum = new sumValue();

        class Adder implements Runnable {

            // used to distinguish threads
            private int id;

            Adder(int index) { id = index; }

            public void run() { sum.add(1); }

        }    

        // start threads
        Thread[] threads = new Thread[1000];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Adder(i) {});
            threads[i].start();
        }

        // wait for threads above to finish
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(sum.sum);
    }
}

3 个答案:

答案 0 :(得分:0)

正如Sotirios所建议的,如果我们在这里更改代码:

public /*synchronized*/ void add(int i) {
    for (int j = 0; j < 1000; j++) {
        sum += i;
    }
}
到目前为止通常不会有一百万。因此需要同步。感谢。

答案 1 :(得分:0)

这种陈述不能总是被认为是原子的:

sum += i; 

实际上,这一步涉及三个步骤(计算临时变量以存储sum的当前值。)

即使volatile变量声明中的sum关键字在这种情况下也不相关(因为赋值基于其当前值)。

因此,您应该取消注释synchronized关键字以启用锁定,以便在您的流程中不会遇到“意外”=&gt;意味着始终以1000结束。

答案 2 :(得分:0)

synchronized关键字不应该被注释掉。每当您从多个线程写入变量时,(至少)写入本身应该受到某种同步的保护 - synchronized关键字,ReentrantReadWriteLock等。你在问题中提到,原因是个人写作不能保证是原子的。

虽然我怀疑此代码的目的是证明一点,但值得注意的是,您不需要使用锁来获取此代码;您可以使用AtomicInteger代替int sum变量,而不使用任何类型的同步来获得正确的解决方案。

具体来说,您可以将public int sum替换为public AtomicInteger sum=new AtomicInteger();,将add()的正文替换为:

public void add(int i) {
    sum.addAndGet(i);
}

...现在你有一个无锁,正确的实现。 (您必须更新其他几个地方的代码才能打印并填充和运行,但我会将其作为练习留给读者。)