使用同步方法改变输出

时间:2013-02-17 05:57:26

标签: java multithreading

我编写了一个多线程和同步递增函数,但它没有显示一致的输出: -

$ java Main
count: 999883

$ java Main
count: 1000000

$ java Main
count: 999826

$ java Main
count: 1000000

$ java Main
count: 1000000

我有一个同步计数器: -

public class Counter {
    public int count;
    synchronized void inc() {
        count = count+1;
    }
    int getCount() {
        return count;
    }
}

使用计数器对象初始化的线程类,并将其递增1000次: -

public class CountPrimesRunnable implements Runnable {
    private Counter c;

    public CountPrimesRunnable(Counter c) {
        this.c = c;
    }

    public void run() {
        for (int i = 0; i < 1000; i++)
            c.inc();
    }
}

一次创建1000个线程的Main类: -

public class Main {
    public static void main(String[] args) {
        int numberOfThreads = 1000;
        Thread[] worker = new Thread[numberOfThreads];
        Counter c = new Counter();
        for (int i = 0; i < numberOfThreads; i++)
            worker[i] = new Thread(new CountPrimesRunnable(c));

        for (int i = 0; i < numberOfThreads; i++)
            worker[i].start();

        System.out.println("count: " + c.count);
    }
}

我错过了什么?

2 个答案:

答案 0 :(得分:4)

  

但它没有显示一致的输出: -

那是因为,从代码中可以确定main线程在所有其他线程完成其工作后总是会完成。在某些情况下,如果得到的结果小于1000000,则在主线程完成后某些线程仍然执行的情况下。

您可以在每个新创建的线程上调用Thread#join()方法,以确保main方法等待所有这些线程死亡,然后在for循环后继续执行。

因此,您必须添加另一个for循环以在每个启动的线程上调用join,并且您还可以避免使用第二个for循环,将其与第一个循环合并:

for (int i = 0; i < numberOfThreads; i++) {
    worker[i] = new Thread(new CountPrimesRunnable(c));
    worker[i].start();
}

for (int i = 0; i < numberOfThreads; i++) {
    worker[i].join();
}

当您从join内部Thread A调用Thread B时,Thread B将仅在Thread A死亡后继续执行。

答案 1 :(得分:1)

public class Counter {
    public int count;
    synchronized void inc() {
        count = count+1;
    }

    //this method must also be synchronized for establishing the happens-before relationship
    synchronized int getCount() {
        return count;
    }
}

只有当get和set在同一个锁上同步时,才能保证您会看到最新的值。

此外,您需要调用join并等待所有线程完成执行。