用Java同步人群(第2部分)

时间:2014-04-07 13:55:12

标签: java multithreading synchronization

问题类似于我刚发布的另一个问题(并得到了回答)。所以问题的陈述是一样的: "我正在编写一个演示程序来解释如何在Java中调节一组线程的并发性,但结果并不像我预期的那样。" 这次我想使用锁,这就是代码:

public class Parcount extends Thread {
    private static int N=1000;
    private static int x=0;
    private final ReentrantLock l = new ReentrantLock();
    public static void main(String[] args) 
            throws InterruptedException {
        Thread[] t = new Thread[N];
        int i;
        for ( i=N-1; i>=0; i-- ) { 
            t[i]=new Parcount(); 
            t[i].start();
        }
        for ( i=N-1; i>=0; i-- ) t[i].join();
        System.out.println(x);
    }
    public void run() { l.lock(); x++; l.unlock(); }
}

创建了1000个线程,并且都希望增加x。最终的打印输出应该是1000,但它不是:一些增量会丢失。代码似乎很简单,但我可能错过了一些东西: - /

谢谢...

3 个答案:

答案 0 :(得分:1)

每个线程都有一个锁,每个线程获得它自己的锁。您希望为每个所有线程提供一个锁定以获得正确的同步。

答案 1 :(得分:0)

问题在于锁定的范围与其保护范围相同,因此l必须是static,如下所示:

private static int x=0;
private static final ReentrantLock l = new ReentrantLock();

请注意,我可能会使用ExecutorService来启动所有主题,将Parcount改为Runnable,改为xAtomicInteger(前面的需要一个ReentrantLock),允许线程数作为命令行参数传递,并将一些名称更改为更具描述性:

public class Parcount implements Runnable {

    private static final int threadCount;

    private static AtomicInteger value = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException {
        try { threadCount = Integer.valueOf(args[0]); } //get N as a command line argument
        catch(NumberFormatException | ArrayIndexOutOfBoundsException e) { threadCount = 1000; }

        ArrayList<Callable<?>> tasks = new ArrayList<>(threadCount);

        for(int idx = 0; idx < threadCount; idx++)
            tasks.add(Executors.callable(new Parcount()));

        Executors.newFixedThreadPool(threadCount).invokeAll(tasks);
        //no need to manually join them all: invokeAll automatically waits  

        System.out.println(x);
    }

    public void run() {
        value.getAndIncrement(); //AtomicInteger synchronizes access automatically
    }
}

答案 2 :(得分:0)

谢谢Eugene!根据您的解决方案,以下是显式代码:

public class Parcount extends Thread {
private static int N=1000;
private static int x=0;
private static final ReentrantLock l = new ReentrantLock();
public static void main(String[] args) 
        throws InterruptedException {
    Thread[] t = new Thread[N];
    int i;
    for ( i=N-1; i>=0; i-- ) { 
        t[i]=new Parcount(); 
        t[i].start();
    }
    for ( i=N-1; i>=0; i-- ) t[i].join();
    System.out.println(x);
}
public void run() { l.lock(); x++; l.unlock(); }

}