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;
    }
}
public类SyncTest扩展线程{
私有静态整数syncObj=新整数(0);
私有静态SyncTest[]线程=新SyncTest[10];
私有布尔完成=假;
公开募捐{
对于(int i=0;i<1000;i++){
已同步(syncObj){
syncObj++;
}
}
完成=正确;
}
公共静态void main(字符串[]args){
对于(int i=0;i

有人能澄清一下吗?

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

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

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

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

private static final Object syncObject = new Object(); 
那么你的计数器应该是perofrmance的原语(int),称它为“counter”或其他什么

在syncObject和增量计数器上同步


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

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

我已将同步块更改为

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

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


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

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