Java 同步多线程将1添加到数字,结果不同

Java 同步多线程将1添加到数字,结果不同,java,multithreading,Java,Multithreading,我不知道这是否正确,但我正在尝试使用1000个线程向变量添加1。然后,我在最后打印出数字,以验证它是否有效,它永远不会是1000,并且也会发生变化 我通过谷歌搜索确定这可能是一个同步问题,但当我尝试同步线程时,最后的线程数仍然不是1000,而且变化幅度更小(在995到997之间变化,而在不同步的情况下,大致在900到1000之间变化) 以下是我目前正在做的事情: public class Main extends Thread{ public static void main(Stri

我不知道这是否正确,但我正在尝试使用1000个线程向变量添加1。然后,我在最后打印出数字,以验证它是否有效,它永远不会是1000,并且也会发生变化

我通过谷歌搜索确定这可能是一个同步问题,但当我尝试同步线程时,最后的线程数仍然不是1000,而且变化幅度更小(在995到997之间变化,而在不同步的情况下,大致在900到1000之间变化)

以下是我目前正在做的事情:

public class Main extends Thread{

    public static void main(String[] args) {

        Thread[] threads = new Thread[1000];

        Adder adder = new Adder();

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new ThreadAddSync(adder));
            threads[i].start();

        }

        System.out.println("----- " + adder.count);
    }
}

public class ThreadAddSync implements Runnable{

    Adder add;

    public ThreadAddSync(Adder add){
        this.add = add;
    }

    @Override
    public void run() {
        synchronized(add){
            add.add();
        }
    }
}

public class Adder {

    int count = 0;

    public void add(){
        count += 1;
    }
}
public类主线程扩展{
公共静态void main(字符串[]args){
线程[]线程=新线程[1000];
加法器加法器=新加法器();
对于(int i=0;i

我的问题是这些线程是否应该按照我编写的方式同步?如果它们是同步的,那么如果它们在技术上是安全的,为什么会产生不同的结果呢?

System.out.println(“----”+adder.count)
-您访问
计数
,但不
加法器上同步
,因此,不安全(如果您希望在打印总数之前看到最终总数,也没有等待工作人员完成,
join()
,或者添加另一个循环等待)。另外,在实际代码中,您应该使用

您不需要等待线程完成,所以您要在工作完成之前打印结果。您需要对每个线程调用第二个循环。@Andreas,好的,我以前做过,但在循环中我启动了线程,所以我在做开始,然后立即加入,我想这意味着在前一个线程完成否定线程点之前,它不会启动下一个线程。但如果我在开始循环后这样做……我知道这是有道理的。即使是同步的,结果也可能是错误的,因为OP从不等待线程完成,所以打印结果可能太早了。@Andreas是的,我假设OP有某种机制是主线程来观察总数,并看到总数跳跃(不同的结果)。如果它确实是发布的,那么我同意你的看法。好吧,这样就行了,现在它每次显示1000,但是当我删除同步,使其不安全地运行时,它仍然会达到1000。这有意义吗?我想它偶尔会写相同的数字,而计数不会达到1000?@Redcoatwright你的线程非常短-生存,所以冲突的概率很小。尝试在
运行
方法的循环中多次(1000+)调用
add.add()
。@Redcoatwright同样,启动线程需要时间,所以创建两个线程,一个线程的计数为1000,另一个线程的计数为1。让线程
倒计时()
大的线程,然后
等待()进入上述循环之前,在小循环上执行
。在主线程中,在
start()
join()
循环之间,在大循环上执行
wait()
,然后在小循环上执行
countDown()
。这将确保在线程开始工作之前完成启动线程的开销。