我想知道为什么这个结果不是1000000

时间:2019-06-05 02:48:39

标签: java multithreading java-threads

我使用线程池创建了100个线程,增加了资金,并使用了同步,但是结果没有达到1000000。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool {

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(100);
        for(int i=0;i<100;i++) {
            Thread t=new MyThread();
            pool.execute(t);
        }
        pool.shutdown();
    }
}

class MyThread extends Thread{

    private static int money=0;

    @Override
    public void run() {
        addMoney();
    }

    public synchronized void addMoney() {
        for(int i=0;i<10000;i++)
            money+=1;
        System.out.println(money);
    }
}

2 个答案:

答案 0 :(得分:1)

您添加到synchronized方法中的addMoney关键字使用this作为内在锁。由于this指向每个线程实例,并且每个线程仅调用一次此方法,因此没有效果。

要在线程之间同步访问,可以显式指定全局锁实例,例如ThreadPool类:

public void addMoney() {
    synchronized(ThreadPool.class) {
        for(int i=0;i<10000;i++)
            money+=1;
        System.out.println(money);
    }
}

通过将addMoney方法声明为static,可以实现几乎相同的效果。在这种情况下,内部锁将改为MyThread类:

public static synchronized void addMoney() {
    for(int i=0;i<10000;i++)
        money+=1;
    System.out.println(money);
}

您可以在Java文档https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

中找到更多详细信息。

答案 1 :(得分:0)

问题是访问和更新共享静态变量时,每个任务都在不同的对象上同步。这意味着工作线程之间没有相互排斥。这意味着您的应用程序计算出的值可能是不可预测的和/或特定于平台的。 (除非你很幸运...)

一种解决方法是将addMoney更改为static synchronized方法。这将导致线程在MyThread.class对象上同步。但是,如果执行此操作,则会发现您的应用程序是有效单线程...因为只有您的MyThread实例之一才能执行其addMoney方法一次。

目前尚不清楚正确的解决方法是什么,因为尚不清楚此“玩具”示例试图演示什么。但是我提到的替代方法至少应该可靠地计算结果。


您不应该扩展Thread。您的MyThread类应替换为实现Runnable的类。您在这里所做的是使用Thread对象,就好像它只是一个Runnable。那是个坏主意。您使用的ExecutorService将负责线程的创建。您需要为它提供“任务”而不是“线程”。