簡體   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