Java 同步关键字不';行不通 PackageThreadShareResource1; 公共类非同步1{ 私有整数和=0; 公共静态void main(字符串[]args){ 非同步1 n=新的非同步1(); n、 任务(); System.out.println(n.getSum()); } 公共同步的void sumAddOne(){ sum++; } 公开作废任务(){ 对于(int i=0;i

Java 同步关键字不';行不通 PackageThreadShareResource1; 公共类非同步1{ 私有整数和=0; 公共静态void main(字符串[]args){ 非同步1 n=新的非同步1(); n、 任务(); System.out.println(n.getSum()); } 公共同步的void sumAddOne(){ sum++; } 公开作废任务(){ 对于(int i=0;i,java,multithreading,synchronization,Java,Multithreading,Synchronization,如果没有代码的注释部分,程序就会出现数据损坏,而不是每次运行时都是100。但是我认为synchronized关键字应该在sumAddOne方法上获得一个锁,它是我程序的关键区域,允许一个线程每次访问这个方法 我也尝试过使用ExecutorService,但它不能提供100次所有的运行 package threadShareResource1; public class NonSynchro1 { private int sum = 0; public static void

如果没有代码的注释部分,程序就会出现数据损坏,而不是每次运行时都是100。但是我认为synchronized关键字应该在sumAddOne方法上获得一个锁,它是我程序的关键区域,允许一个线程每次访问这个方法

我也尝试过使用ExecutorService,但它不能提供100次所有的运行

package threadShareResource1;

public class NonSynchro1 {
    private int sum = 0;

    public static void main(String[] args) {
        NonSynchro1 n = new NonSynchro1();
        n.task();
        System.out.println(n.getSum());
    }

    public synchronized void sumAddOne(){
        sum++;
    }

    public void task(){
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable(){
                @Override
                public void run() {
                    sumAddOne();
                }
            }).start();

        /*  try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   */
        }
    }
    public int getSum() {
        return sum;
    }
}
公共作废任务(){
ExecutorService s=Executors.newCachedThreadPool();
对于(int i=0;i<100;i++){
s、 执行(新线程(新Runnable()){
@凌驾
公开募捐{
sumAddOne();
}
}));
}
s、 关机();
而(!s.isTerminated()){}
}
在Task()中,您可以启动100个线程(这是一个很大的数目),每个线程的总数加1

但当任务完成时,您所知道的是,100个线程正处于启动过程中。在调用println()之前不会阻塞,因此如何知道所有线程都已完成

睡眠可能“防止了损坏”,因为它给了系统时间来完成所有线程的启动


除此之外,您还可以正确使用Synchronized。在任何地方,多个线程可能会写入您需要的同一个变量,通常(简化),如果您只是在读取,则不需要该变量。

synchronized关键字使用正确,问题是您没有等待线程完成。以下是一个可能的解决方案:

public void task(){
    ExecutorService s = Executors.newCachedThreadPool();

    for (int i = 0; i < 100; i++) {
        s.execute(new Thread(new Runnable(){
            @Override
            public void run() {
                sumAddOne();
            }
        }));
    }
    s.shutdown();

    while(!s.isTerminated()){}
}
公共类非同步1{
私有静态最终ExecutorService ExecutorService=Executors.newCachedThreadPool();
私有整数和=0;
公共静态void main(字符串[]args){
非同步1 n=新的非同步1();
n、 任务();
System.out.println(n.getSum());
executorService.shutdown();
}
公共同步的void sumAddOne(){
sum++;
}
公开作废任务(){
List callables=new ArrayList();
对于(int i=0;i<100;i++){
callables.add(()->{
sumAddOne();
返回null;
});
}
期货上市;
试一试{
futures=executorService.invokeAll(可调用项);
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
futures.forEach(未来->{
试一试{
future.get();
}捕获(ExecutionException | InterruptedException e){
抛出新的运行时异常(e);
}
});
}
公共整数getSum(){
回报金额;
}
}
首先,我们创建一个可调用的列表——一个将并行执行的函数列表

然后我们在executor服务上调用它们
newCachedThreadPool
我在这里使用过,默认情况下有0个线程,它将创建尽可能多的线程来执行所有传递的可调用项,这些线程在空闲一分钟后将被终止

最后,在for each循环中,我们解析所有未来
get()
调用将被阻止,直到executor服务执行该函数为止。如果在函数内部抛出异常,它也会抛出异常(如果不调用
get()
,您根本看不到这种异常)


另外,当您想要优雅地终止程序时,最好关闭executor服务。在本例中,它只是main方法末尾的
executorService.shutdown()
。如果不这样做,当空闲线程被终止时,程序将在一分钟后终止。但是,如果使用不同的执行器服务,线程可能不会在空闲时终止,在这种情况下,程序将永远不会终止。

为了完整性起见:下面是一个解决方案,说明如何使原始程序等待所有线程由它们完成:

它需要
task
返回它创建的线程。在这种情况下,我们不需要将缓存管理器或集合的事情复杂化:一个简单的数组就可以了。下面是完整的课程:

        for (Thread t : n.task())
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
公共类test1{
私有整数和=0;
公共同步的void sumAddOne(){
sum++;
}
公共线程[]任务(int n){
线程[]线程=新线程[n];
对于(int i=0;i
预期的行为是什么?您试图实现什么?测试100个线程何时使用同步访问公共变量。所有运行的结果都应该是100。你完全正确,当我使用
ExecutorService
时,我忘记使用
synchronized
,这就是结果不正确的原因。所以问题和你们描述的一样,比
        for (Thread t : n.task())
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
public class TestSynchro1 {
    private int sum = 0;

    public synchronized void sumAddOne() {
        sum++;
    }

    public Thread[] task(int n) {
        Thread[] threads = new Thread[n];
        for (int i = 0; i < n; i++) {
            (threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    sumAddOne();
                }
            })).start();
        }
        return threads;
    }

    public static void main(String[] args) {
        TestSynchro1 n = new TestSynchro1();
        for (Thread t : n.task(100))
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        System.out.println(n.sum);
    }
}