Java 整数对象的同步块

Java 整数对象的同步块,java,synchronization,Java,Synchronization,我刚刚在Java中遇到了synchronized块,并编写了一个小程序来测试它是如何工作的 我创建了10个线程,让每个线程增加一个整数对象1000倍 因此,对于同步,我假设在所有线程完成它们的工作之后,结果是10000,而在没有同步的情况下,结果是少于10000 然而,同步并不像我预期的那样是wokring 我猜这与对象的不变性有关 我的节目: public class SyncTest extends Thread{ private static Integer syncObj =

我刚刚在Java中遇到了synchronized块,并编写了一个小程序来测试它是如何工作的

我创建了10个线程,让每个线程增加一个整数对象1000倍

因此,对于同步,我假设在所有线程完成它们的工作之后,结果是10000,而在没有同步的情况下,结果是少于10000

然而,同步并不像我预期的那样是wokring

我猜这与对象的不变性有关

我的节目:

public class SyncTest extends Thread{

    private static Integer syncObj = new Integer(0);
    private static SyncTest[] threads = new SyncTest[10];

    private boolean done = false;

    public void run(){
        for(int i = 0; i < 1000; i++){
            synchronized(syncObj){
                syncObj ++;
            }
        }
        done = true;
    }

    public static void main(String[] args) {

        for(int i=0; i < threads.length; i++){
            threads[i] = new SyncTest();
            threads[i].start();
        }

        while(!allDone()); //wait until all threads finished

        System.out.println(syncObj);
    }

    private static boolean allDone(){
        boolean done = true;
        for(int i = 0; i < threads.length; i++){
            done &= threads[i].done; 
        }

        return done;
    }
}

有人能澄清一下吗?

这些操作通常是用原子来完成的。看一看这些结构是专门为多线程计算而设计的。正常的实现不是线程安全的。

syncObject在每次您对它进行++操作时都会发生更改++会将它转换为一个基本的int,增加它,然后将它自动装箱回Integer对象。整数对象是不可变的。。。一旦它们被创建,它们就无法更改

最重要的是,您并不是在所有线程中都使用相同的syncPObj,不同的线程在不同的时间使用不同的SyncObject进行同步

使用一个对象作为同步调用它syncObj,并将其声明为最终对象:

private static final Object syncObject = new Object(); 
那么您的计数器应该是perofrmance的基本int,称之为“counter”或其他什么

在syncObject和增量计数器上同步


编辑:根据@jsn,done标志也被打破了,因为您的代码在isAllDone方法上有一个“紧循环”,这是一个糟糕的做法。您应该使用线程[i]。join在每个线程完成时等待阻塞,然后从中检查状态。使用ExecutorService是“正确的方法”。

假设这是因为Integer对象的不变性

我已将同步块更改为

Integer old = syncObj;
syncObj ++;
System.out.println(syncObj == old);
我的控制台充满了谎言

因此,每次我增加整数,就会创建一个新对象


因此,我只读取旧对象,它不会被锁定。

但是同步并不像预期的那样工作。-发生了什么意外情况?@jsn volatile不是必需的,因为其他线程没有更改它。@Ravi,你说得对。它不会在线程外更改。我仍然担心主线程可能会将它们中的每一个缓存为false。@jsn您是对的,主线程可能不会获取设置为true的值。OP应该使用线程[i]。joinIt不仅仅是缓存部分,它是waitingOP试验同步时100%CPU的紧密循环。