繁体   English   中英

确保所有等待线程完成

[英]Ensuring all waiting threads complete

我正在建立一个系统,其中调用线程的进度取决于两个变量的状态。 一个变量由外部源(与客户端线程分离)偶尔更新,并且在两个变量的条件下多个客户端线程被阻塞。 系统是这样的

TypeB waitForB() { // Can be called by many threads.
    synchronized (B) {
        while (A <= B) { B.wait(); }
        A = B;
        return B;
    {
}

void updateB(TypeB newB) { // Called by one thread.
    synchronized (B) {
        B.update(newB);
        B.notifyAll(); // All blocked threads must receive new B.
    }
}

一旦更新了B,我需要所有阻塞的线程来接收B的新值。 但是问题是,一旦单个线程完成并更新了A,等待条件就再次变为真,因此其他一些线程被阻塞并且不接收B的新值。是否有办法确保只有最后一个线程在B更新A或其他获得此行为的方式上被阻止了?

我的建议是使用基于事件的方法,其中线程要了解新的B值,只需注册更改! 而单线程只是调用(触发)它们。
这样的事情。
首先声明事件标志。

interface EventListener{
void onUpdate(TypeB oldOne,TypeB newOne);
}

然后将其实现为侦听器。

class ManyThread implements EventListener,Runnable{
...
private TypeA a;
  synchronized void onUpdate(TypeB oldOne,TypeB newOne){
    if(!oldOne.equals(newOne)){a=newOne;this.notify();}
  }

  public ManyThread(){SingleThread.registerListener(this);}
  public synchronized void run(){
     this.wait();//waiting for an event!
     //some business
  }
...
}

然后提供事件发布者。

final class EventMgr{//would be as a singleton  guy too
  private EventMgr(){}
  static private java.util.List<EventListener> li=new java.util.ArrayList<EventListener>();
  static synchronized public void registerListener(EventListener e){li.add(e);}
  static synchronized void triggerListeners(TypeB oldOne,TypeB newOne){
    for(EventListener e:li){e.onUpdate(oldOne,newOne)}
  }
}

和简单的触发侦听器由EventMgr家伙

class SingleThread{
   TypeB oldOne,B;
   void updateB(TypeB newB) { // Called by one thread.
      synchronized (B) {
        oldOne=B.clone();
        B.update(newB);
        //B.notifyAll();
        EventMgr.triggerListeners(oldOne,B);
      }
   }
}

我有以下想法:为了让线程计数器等待B的“良好”值,首先唤醒它们将缓存该良好值,并让其他读者在此之前读取它。 我们将新读者拒之门外,直到所有之前的回合线程完成。

这是代码概述:

final AtomicInteger A = new AtomicInteger(-1), B = new AtomicInteger(-1);
int cachedB = -1;

int readersCount;

int waitForB() throws InterruptedException { // Can be called by many threads.
    synchronized (B) {
        while (cachedB != -1) B.wait();

        readersCount ++;

        while (A.get() <= B.get()) { B.wait(); }

        if (cachedB == -1) {
            cachedB = B.get();
            A.set(B.get());

            readersCount--;
            if (readersCount == 0) { cachedB = -1; B.notifyAll(); }

            return B.get();
        } else {
            int ret = cachedB;

            readersCount--;
            if (readersCount == 0) { cachedB = -1; B.notifyAll(); }

            return ret;
        }
    }
}

void updateB(int newB) { // Called by one thread.
    synchronized (B) {
        B.set(newB);
        B.notifyAll(); // All blocked threads must receive new B.
    }
}

我不确定这是否是100%线程安全的,但尚未发现任何问题。 这个想法是这样的:

CyclicBarrier barrier;
AtomicInteger count = 0;

TypeB waitForB() { // Can be called by many threads.
    synchronized (B) {
        count++;
        while (A <= B) { B.wait(); }
        count--;
    {
    if (barrier != null) { barrier.await(); }
    return B;
}

class UpdateA implements Runnable {
    void run() {
        A = B;
    }
}

void updateB(TypeB newB) { // Called by one thread.
    synchronized (B) {
        B.update(newB);
        barrier = new CyclicBarrier(count, new UpdateA);
        B.notifyAll(); // All blocked threads must receive new B.
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM