我有一个getNewA()方法,它应该在其他线程调用setA(x)之前阻塞。使用CountDownLatch是否正确?我注意到有一个数据竞争,在gate.await()解锁之后,另一个线程可能会使用旧的闩锁调用setA(x),因此可能会遗漏一个值。我考虑过同步getNewA(),但这不会导致死锁吗?对于如何处理这个问题,有什么建议吗?
package test;
import java.util.concurrent.CountDownLatch;
public class A {
private int a;
private CountDownLatch gate;
public A(int a) {
a = 1;
gate = new CountDownLatch(1);
}
A getNewA() throws InterruptedException { // wait for new a...
gate.await();
gate = new CountDownLatch(1);
return this;
}
public synchronized int getA() {
return a;
}
public synchronized void setA(int a) {
gate.countDown();
this.a = a;
}
}发布于 2012-03-24 05:07:01
使用Phaser。你可以像你想要的那样在这里重用它,而不需要创建一个新的屏障实例。
public class A {
private int a
private final Phaser phaser = new Phaser(1);
public A(int a) {
a = 1;
}
A getNewA() throws InterruptedException { // wait for new a...
phaser.awaitAdvance(phaser.getPhase());
return this;
}
public synchronized int getA() {
return percent;
}
public synchronized void setA(int a) {
this.a = a
phaser.arrive();
}
}每次调用setA时,它将递增到一个新的阶段,并且phaser.awaitAdvance(phaser.getPhase())将返回。此时,新阶段将等于phaser.getPhase()+1
注意:这需要Java7。
发布于 2012-03-24 06:17:21
另一种方法是自己处理同步。我认为您需要的是让getA返回一个值,该值是在线程当前进入之后设置的。您可以将其用作wait()标准。
public class A {
private int a;
private long updateCount = 0;
private final Object lock = new Object();
public A getNewA() throws InterruptedException { // wait for new a...
synchronized(lock) {
long currentCount = updateCount ;
while (currentCount == updateCont) {//assumes never decrementing
lock.wait();
}
return this;
}
}
public int getA() {
synchronized(lock) {
return a;
}
}
public void setA(int a) {
synchronized(lock) {
this.a = a;
updateCount++;
lock.notifyAll();
}
}
}编辑:正如TomAnderson提到的,竞争条件是可能的。谢谢
发布于 2012-03-24 05:53:38
您可以使用Semahore
package test;
import java.util.concurrent.Semaphore;
public class A {
private int a
private Semaphore semaphore = new Semaphore(0);
public A(int a) {
a = 1;
}
A getNewA() throws InterruptedException { // wait for new a...
semaphore.acquire();
return this;
}
public synchronized int getA() {
return percent;
}
public synchronized void setA(int a) {
this.a = a;
semaphore.release();
}
}如果信号量只剩下0个许可,并且两个线程相继调用getA,则这两个线程都将阻塞,并且在调用setA时,不确定地选择其中只有一个线程被唤醒。
如果setA在一个序列中被调用两次,它将允许两个线程下次调用getA,这可能不是您想要的,因为这两个线程都将获得对this的相同引用。
https://stackoverflow.com/questions/9846307
复制相似问题