Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 倒计时锁存同步_Java_Multithreading_Concurrency - Fatal编程技术网

Java 倒计时锁存同步

Java 倒计时锁存同步,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个getNewA()方法,该方法应该一直阻塞,直到其他线程调用setA(x)。使用倒计时锁存器正确吗?我注意到有一种数据竞争,在gate.await()解除阻塞后,另一个线程可能会使用旧锁存器调用setA(x),因此可能会丢失一个值。我考虑过同步getNewA(),但这不会导致死锁吗?关于如何处理这个问题有什么建议吗 package test; import java.util.concurrent.CountDownLatch; public class A { priva

我有一个getNewA()方法,该方法应该一直阻塞,直到其他线程调用setA(x)。使用倒计时锁存器正确吗?我注意到有一种数据竞争,在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;
    }
}
使用一个。您可以像在这里一样重用它,而无需创建屏障的新实例

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


注意:这需要Java 7。

您可以使用
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
,这可能不是您想要的,因为它们都将获得对
的相同引用,这

另一种方法是自己处理同步。我认为您需要的是
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();
        }
    }
}

编辑:如Anderson所述,竞争条件是可能的。谢谢

如果另一个线程在
getNewA()
之前调用
setA
,那意味着什么?如果setA在getNewA()之前,那么信号量对您更有用吗。调用getNewA()的线程将返回实例而不阻塞,如果在调用
getNewA()
之前调用了两次
setA()
,那么会发生什么?对
getNewA()
的两个调用可以不阻塞地通过吗?如果两个线程都在等待
getNewA()
,并且有一个
setA()
调用传入,那么这两个线程都应该被解锁还是只有一个?您确实需要仔细描述您的情况:)是否应该
getNewA
真的返回A,而不是int?当前代码有一个争用条件:如果两个线程调用
getNewA()
并阻塞,那么另一个线程将其唤醒,然后第四个线程立即调用
getNewA()
,第四个线程可能会看到一个值
gate
,该值由第一个线程设置为离开gate,但在任何
setA()
调用线程有机会看到它之前,该值会被第二个线程覆盖以离开gate。这个可怜的第四个线程将永远不会被解锁。如果我使用java 6,还有其他选择吗?@xxtommoxx我想到了FutureTask的一些用法,但不太喜欢它来发布它。我也许能做得更好。@lhballoti不幸的是不能。SynchronousQueue要求放置线程等待,直到有一个拉动线程。这一要求要求线程只发送信号并继续工作。如果没有线程在等待信号,那也没关系。@JohnVint事实上,我没有想到Puting线程会阻塞。如果在同一毫秒内得到多个更新,那么使用这样的时间戳很容易受到竞争条件的影响,而毫秒在计算中是很长的时间。你最好使用计数器而不是时间戳;所有访问都受
锁上的同步保护。可以将其视为一种不同寻常的成对编程@都铎不一定。正如您在回答中提到的,信号量不会通知所有线程唤醒。