java - 如果非空则使用值,否则等待并原子地获取它,在循环中重复

标签 java multithreading

假设对象中的一个字段根据一个线程的操作,从 null 到非 null 以及来回变化等。

每当第二个线程碰巧获得非空值时,它就会惰性地采取一些操作。特别是,第二个线程应等待,直到该值切换为非空。如果它超出了等待范围,我想确保它手中有一个非空值。

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

它也不适合信号量使用,因为它同样不会.acquire() 许可。

相反,它让人想起内置等待的比较和获取,但这似乎不存在。

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

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

最佳答案

这是一个依赖 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);
  }

}

关于java - 如果非空则使用值,否则等待并原子地获取它,在循环中重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39438188/

相关文章:

带有动态优先级标志的java队列

java - 如何在 Alpine docker 容器上使用 openjdk 14 启用 ECDHE 密码?

linux - pthread 互斥体解锁如何工作?线程是否同时出现?

android - 由于多线程中的 free() 调用导致程序随机崩溃

Java多线程等待状态

java - 用于访问具有不同字段名称的相似对象的设计模式

java - 为什么这个并发执行总是给我相同的跟踪?

java - 如何改进android studio的编辑器?

.net - 在多线程期间共享数据 - 非静态变量可以吗?

c++ - pthread 执行时间比顺序执行时间差