[英]CountDownLatch Synchronization
I have a method getNewA() that is supposed to block until some other thread calls setA(x). 我有一个方法getNewA(),它应该阻塞,直到其他一些线程调用setA(x)。 Is it correct to use a CountDownLatch? 使用CountDownLatch是否正确? I noticed that there is a data race in that there is a possibility that after gate.await() unblocks another thread will call setA(x) using the old latch, therefore it might be possible to miss a value. 我注意到有一个数据竞争,有可能在gate.await()取消阻塞后,另一个线程将使用旧锁存器调用setA(x),因此可能会错过一个值。 I thought about synchronizing getNewA() but wouldn't that result in a deadlock? 我想同步getNewA()但不会导致死锁吗? Any suggestions on how to approach this? 有关如何处理此问题的任何建议?
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;
}
}
Use a Phaser . 使用Phaser 。 You can reuse it just like you want here without having to create a new instance of the your barrier. 您可以像在此处一样重复使用它,而无需创建障碍的新实例。
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();
}
}
Each time setA
is called it will increment to a new phase and the phaser.awaitAdvance(phaser.getPhase())
will return out. 每次调用setA
,它都会增加到一个新阶段, phaser.awaitAdvance(phaser.getPhase())
将返回。 At this point the new phase will equal the phaser.getPhase()+1
此时,新阶段将等于phaser.getPhase()+1
Note: this requires Java 7. 注意:这需要Java 7。
An alternative is to handle synchronization yourself. 另一种方法是自己处理同步。 What I think you want is for the getA
to return a value that is set after a thread currently enters. 我认为你想要的是让getA
返回一个当前进入线程后设置的值。 You can use this as the wait()
criteria. 您可以将其用作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();
}
}
}
Edit: Race condition is possible as TomAnderson mentioned. 编辑:汤姆安德森提到的竞争条件是可能的。 Thanks 谢谢
You could use a Semahore
: 你可以使用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();
}
}
If the semaphore has 0 permits left and two threads call getA
one after the other, both will block and only of them will be non-deterministically chosen to wake up when setA
is called. 如果信号量剩下0个许可,两个线程一个getA
一个地调用getA
,则两个线程都将阻塞,并且只有在调用getA
时setA
确定地选择它们才能唤醒。
If setA
is called twice in a sequence, it will allow two threads to call getA
next time, which may not be what you want, since both of them will get the same reference to this
. 如果setA
是序列叫了两声,这将允许两个线程调用getA
下一次,你想要的东西可能不是,因为他们都将获得相同的参照this
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.