我的代码如下:
WorkPool.java
import java.util.LinkedList;
/**
* Class that implements a work pool based on the model of "replicated workers"
* Tasks introduced in the work pool are objects of type MRCTask
*
*/
public class WorkPool {
int nThreads; //total number of worker threads
int nWaiting = 0; //number of worker threads blocked waiting for a task
public boolean ready = false; //problem is finished
LinkedList<MRCTask> tasks = new LinkedList<MRCTask>();
/**
* Constructor for class WorkPool.
* @param nThreads - number of worker threads
*/
public WorkPool(int nThreads) {
this.nThreads = nThreads;
}
/**
* Function which tries to obtain a task from the work pool
* If there are not available tasks, the function hangs until
* a task can be given or until the problem is finished
* @return A task to solve or null if the problem is finished
*/
public synchronized MRCTask getWork() {
if (tasks.size() == 0) { //empty work pool
nWaiting++;
/*
* finish condition:
* there is no available task in the work pool and no worker
* is active
*/
if (nWaiting == nThreads) {
ready = true;
/* problem is finished, announcing all workers */
notifyAll();
return null;
} else {
while (!ready && tasks.size() == 0) {
try {
this.wait();
} catch(Exception e) {e.printStackTrace();}
}
if (ready)
/* work is done */
return null;
nWaiting--;
}
}
return tasks.remove();
}
/**
* Function which inserts a task in the work pool
* @param sp The task which must be introduced
*/
synchronized void putWork(MRCTask sp) {
tasks.add(sp);
/* announcing one of the waiting workers */
this.notify();
}
}
TestMain.Java
public class TestMain {
public static void main(String[] args) throws InterruptedException {
int nr_proc = Runtime.getRuntime().availableProcessors();
WorkPool wp = new WorkPool(nr_proc);
MRCTask.t = 0;
for(int i = 0; i < 10000; i++)
wp.putWork(new MRCTask());
Worker[] wrk = new Worker[nr_proc];
for(int i = 0; i < nr_proc; i++)
wrk[i] = new Worker(wp);
for(int i = 0; i < nr_proc; i++)
wrk[i].start();
for(int i = 0; i < nr_proc; i++)
wrk[i].join();
System.out.println(MRCTask.t);
}
}
class Worker extends Thread {
WorkPool wp;
public Worker(WorkPool wp) {
this.wp = wp;
}
void work(MRCTask ps) throws Exception {
ps.processTask();
}
public void run() {
while (true) {
MRCTask ps = wp.getWork();
if (ps == null)
break;
try {
work(ps);
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
}
class MRCTask {
static int t;
public void processTask() {
t += 5;
}
}
运行此代码时,我通常希望得到50000作为答案。这只发生在nr_proc为1时。当nr_proc为2或4时(在我的情况下,availableProcessor()返回4),我得到随机值,如49960,49900,49995,有时甚至50000。 你能告诉我有什么问题吗? 提前致谢并抱歉这个庞大的代码! PS:我试图修改函数processTask(),如下所示:
public void processTask() {
synchronized(this) {
t += 5;
}
}
但是,我仍然遇到同样的问题。我认为同步部分会有所帮助,但他们没有。
答案 0 :(得分:1)
您的值t
是静态的。所以你试图同步事物的方式,注定要失败。实际上你没有同步任何东西,因为你有许多不同的MRCTask
实例(实际上是10000)。他们每个人都有一个单独的锁/监视器。
尝试将MRCTask
中的代码更改为:
private static final Object LOCK = new Object();
public void processTask() {
synchronized (LOCK) {
t += 5;
}
}
这是不同的,现在您使用共享锁。 看看你是否仍然得到不可预测/随机的结果。你不会。 以前你只是有一个古典的竞争条件。