问题类似于我刚发布的另一个问题(并得到了回答)。所以问题的陈述是一样的: "我正在编写一个演示程序来解释如何在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,但它不是:一些增量会丢失。代码似乎很简单,但我可能错过了一些东西: - /
谢谢...
答案 0 :(得分:1)
每个线程都有一个锁,每个线程获得它自己的锁。您希望为每个所有线程提供一个锁定以获得正确的同步。
答案 1 :(得分:0)
问题在于锁定的范围与其保护范围相同,因此l
必须是static
,如下所示:
private static int x=0;
private static final ReentrantLock l = new ReentrantLock();
请注意,我可能会使用ExecutorService
来启动所有主题,将Parcount
改为Runnable
,改为x
和AtomicInteger
(前面的需要一个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(); }
}