我在java中实现了一个障碍,当它被一个线程接收时,它会创建一个新对象,该参数的值存储在一个私有变量中,以后再返回。然后,当另一个线程调用屏障时,它使用另一个参数完成前一个对象。第一对顺利进行,其余对接收第一对创建的相同对象。
private Barrier aBarrier;
private boolean first = true;
public synchronized Barrier pairUp(int id){
try{
if(first){
first = false;
aBarrier = new Barrier(); aBarrier.setFirst(id);
wait();
}
else{
first = true;
aBarrier.setLast(id);
notify();
}
}
catch(InterruptedException e){System.out.printf("ERROR");}
return aBarrier;
}
这就是调用上述方法的每个进程的样子。
private int id = ID OF THE PROCESS, 14 RUN CONCURRENTLY SO FROM 0 TO 13 (this is set in the constructor method);
public void run() {
while(true){
myBarrier = pairUp(id);
myBarrier.goThrough();
//Do stuff that doesn't matter here
// ....
}
}
一个Barrier对象包含两个整数和一个稍后会做更多事情的方法。 如果我在调用之前或之后将私有变量aBarrier重置为null,它总是返回null。 我觉得我在这里错过了一些愚蠢的事情。
如果一个进程在第一对之后调用方法pairUp(),它将获得第一个Barrier。 我使用它来区分在pairUp方法中首先出现的进程。
事先谢谢!
答案 0 :(得分:0)
一个Barrier对象包含两个整数和一个稍后会做更多事情的方法。如果我在调用之前或之后将私有变量aBarrier重置为null,它总是返回null。我觉得我在这里错过了一些愚蠢的事情。
我认为问题是你在等待/通知调用之后返回aBarrier
,但它可能已被后续线程更改。将它存储在局部变量中以便不会被更改是关键。
您可能还有多个版本的包装对象,因此您的synchronized
语句正在同步另一个对象?
请在下面的代码中注意事项:
System.out.println(...)
更改同步。这里需要小心。aBarrier
为null或不用来替换first
布尔值。代码:
public class Foo implements Runnable {
private static int NUM_THREADS = 14;
private static final AtomicInteger idCounter = new AtomicInteger();
private static final ExecutorService threadPool = Executors.newFixedThreadPool(NUM_THREADS);
private static Barrier aBarrier = null;
public static void main(String[] args) {
// only 1 Foo object
Foo foo = new Foo();
for (int i = 0; i < NUM_THREADS; i++) {
threadPool.execute(foo);
}
}
public synchronized Barrier pairUp(int id) {
Barrier barrier = aBarrier;
try {
if (barrier == null) {
barrier = new Barrier();
barrier.first = id;
aBarrier = barrier;
wait();
} else {
barrier.last = id;
aBarrier = null;
notify();
}
} catch (InterruptedException e) {
// always a good pattern
Thread.currentThread().interrupt();
e.printStackTrace();
barrier = null;
}
// return local barrier because aBarrier might have changed
return barrier;
}
@Override
public void run() {
int id = idCounter.incrementAndGet();
while (true) {
Barrier myBarrier = pairUp(id);
// System.out.println is synchronized so it may move the bug
System.out.println(id + ": " + myBarrier.first + " and " + myBarrier.last);
}
}
private static class Barrier {
int first;
int last;
}
}