Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 如果非null,则使用value,否则等待并原子地获取它,在循环中重复_Java_Multithreading - Fatal编程技术网

Java 如果非null,则使用value,否则等待并原子地获取它,在循环中重复

Java 如果非null,则使用value,否则等待并原子地获取它,在循环中重复,java,multithreading,Java,Multithreading,假设一个对象中的一个字段根据one线程的操作从null变为非null并来回变化,等等 当第二个线程碰巧获得非空值时,它将惰性地执行一些操作。特别是,第二个线程应等待值切换为非空。如果它不在等待中,我想确保它手里有一个非null 这看起来不像是队列情况,因为第二个线程不会带走该元素,它只是在碰巧有一个元素可用时使用它 它也不适合使用信号量,因为它同样不会获得许可证 相反,它让人想起了compare and get with Build in wait,但这似乎并不存在 在java.util.con

假设一个对象中的一个字段根据one线程的操作从null变为非null并来回变化,等等

当第二个线程碰巧获得非空值时,它将惰性地执行一些操作。特别是,第二个线程应等待值切换为非空。如果它不在等待中,我想确保它手里有一个非null

这看起来不像是队列情况,因为第二个线程不会带走该元素,它只是在碰巧有一个元素可用时使用它

它也不适合使用信号量,因为它同样不会获得许可证

相反,它让人想起了compare and get with Build in wait,但这似乎并不存在

java.util.concurrent
中是否有一个预定义的设备,我无法识别。如何做到这一点


类似,但没有公认的答案或对此有帮助的答案。

这是一个依靠
ReentrantLock
管理
volatile
字段的实现。这在很大程度上借鉴了双重检查锁定的习惯用法,但是读取操作不是创建值本身,而是等待一个条件来表示已经设置了值

使用接受超时的版本重载了
get()
方法。两个版本都是可中断的

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BlockingRef<V> {

  private final Lock lock = new ReentrantLock(true);

  private final Condition signal = lock.newCondition();

  private volatile V value;

  public BlockingRef() {
    this(null);
  }

  public BlockingRef(V initialValue) {
    this.value = initialValue;
  }

  public final void set(V value) {
    lock.lock();
    try {
      this.value = value;
      signal.signalAll();
    } finally {
      lock.unlock();
    }
  }

  public final V get() throws InterruptedException {
    V result = value;
    if (result == null) {
      lock.lockInterruptibly();
      try {
        for (result = value; result == null; result = value)
          signal.await();
      } finally {
        lock.unlock();
      }
    }
    return result;
  }

  public final V get(long time, TimeUnit unit) 
    throws TimeoutException, InterruptedException 
  {
    V result = value;
    if (result == null) {
      long start = System.nanoTime();
      if (!lock.tryLock(time, unit)) throw new TimeoutException();
      try {
        time = unit.toNanos(time);
        for (result = value; result == null; result = value) {
          long wait = time - (System.nanoTime() - start);
          if (wait <= 0) throw new TimeoutException();
          signal.await(wait, TimeUnit.NANOSECONDS);
        }
      } finally {
        lock.unlock();
      }
    }
    return result;
  }

  @Override
  public String toString() {
    return String.valueOf(value);
  }

}
import java.util.concurrent.TimeUnit;
导入java.util.concurrent.TimeoutException;
导入java.util.concurrent.locks.Condition;
导入java.util.concurrent.locks.Lock;
导入java.util.concurrent.locks.ReentrantLock;
公共类封锁REF{
私有最终锁定=新的可重入锁定(true);
私有最终条件信号=lock.newCondition();
私有变量V值;
公共封锁REF(){
这个(空);
}
公共封锁参考(V初始值){
this.value=初始值;
}
公共最终无效集(V值){
lock.lock();
试一试{
这个值=值;
signal.signalAll();
}最后{
lock.unlock();
}
}
public final V get()抛出InterruptedException{
V结果=数值;
如果(结果==null){
lock.lockinterruptbly();
试一试{
for(结果=值;结果=空;结果=值)
信号。等待();
}最后{
lock.unlock();
}
}
返回结果;
}
公共最终V get(长时间,时间单位)
抛出TimeoutException、InterruptedException
{
V结果=数值;
如果(结果==null){
长启动=System.nanoTime();
如果(!lock.tryLock(time,unit))抛出新的TimeoutException();
试一试{
时间=单位为托纳诺斯(时间);
for(结果=值;结果=空;结果=值){
长时间等待=时间-(System.nanoTime()-start);

if(wait)你的方法有一个基本缺陷——你不能保证懒惰线程会在字段更改之间醒来,因此它可能不会捕获所有事件。这不是一个基本缺陷,而是预期的行为。这就是为什么我写:“如果它碰巧得到一个空值”。如果没有,这并不重要。多个线程会设置该值吗?啊,好问题。只有一个线程会随该值更改。