簡體   English   中英

如何在Java中同步一組多個線程相對於單個線程

[英]how to synchronize a set of multiple threads with respect to a single thread in Java

假設我有一個名為myList of threads的arraylist,所有這些都是使用實現Runnable接口的類myRunnable的實例創建的,也就是說,所有線程共享相同的代碼以在myRunnable的run()方法中執行。 現在假設我有另一個名為singleThread的線程,該線程是使用實現Runnable接口的類otherRunnable的實例創建的。

我必須為這些線程解決的同步化挑戰如下:我需要myList中的所有線程執行它們的代碼直到某一點。 一旦達到這一點,他們就會睡覺。 一旦所有且只有myList中的所有線程都處於休眠狀態,那么應該喚醒singleThread(singleThread已經處於休眠狀態)。 然后singleThread執行它自己的東西,當它完成時,它應該睡眠並且myList中的所有線程都應該被喚醒。 想象一下,代碼被包含在while(true)中,所以這個過程必須一次又一次地發生。

以下是我剛才描述的情況示例,包括嘗試解決同步問題:

class myRunnable extends Runnable
{
  public static final Object lock = new Object();
  static int count = 0;

  @override
  run()
  { 
     while(true)
     {
        //do stuff
        barrier();
        //do stuff
     }
  }

  void barrier()
  {
     try {
       synchronized(lock) {
          count++;
          if (count == Program.myList.size()) {
             count = 0;
             synchronized(otherRunnable.lock) {           
                otherRunnable.lock.notify();
             }
          }
          lock.wait();
       }
     } catch (InterruptedException ex) {}
  }
}

class otherRunnable extend Runnable
{
   public static final Object lock = new Object();

   @override
   run()
   {
     while(true)
     {
       try {
         synchronized(lock) {
            lock.wait();
       } catch (InterruptedException ex) {}

       // do stuff

       try {
         synchronized(myRunnable.lock) {
           myRunnable.notifyAll();
       }
     }
   }        
}

class Program
{
  public static ArrayList<Thread> myList;

  public static void main (string[] args)
  {
     myList = new ArrayList<Thread>();

     for(int i = 0; i < 10; i++)
     {
        myList.add(new Thread(new myRunnable()));
        myList.get(i).start();
     }
     new Thread(new OtherRunnable()).start();
  }
}

基本上我的想法是使用一個計數器來確保myList中的線程只是等待,除了最后一個線程遞增計數器,它將計數器重置為0,通過通知鎖定喚醒singleThread,然后最后一個線程進入睡眠狀態等到myRunnable.lock。 在更抽象的層面上,我的方法是在myList中為線程使用某種屏障來阻止它們在關鍵點執行,然后擊中屏障的最后一個線程喚醒singleThread並進入睡眠狀態,然后singleThread使其成為東西完成后,它會喚醒屏障中的所有線程,以便它們可以再次繼續。

我的問題是我的邏輯存在缺陷(可能還有更多)。 當最后一個線程觸及屏障通知otherRunnable.lock時,有可能發生直接上下文切換,在最后一個線程可以在myRunnable.lock上執行其等待(並進入休眠狀態)之前將cpu提供給singleThread。 然后singleThread將執行它的所有東西,將在myRunnable.lock上執行notifyAll,並且myList中的所有線程將被喚醒,除了最后一個線程擊中屏障,因為它尚未執行其wait命令。 然后,所有這些線程將再次執行它們的內容並再次觸及屏障,但計數永遠不會等於myList.size(),因為前面提到的最后一個線程最終會再次調度並執行wait。 反過來,singleThread也會在第一行執行wait,結果導致死鎖,每個人都在睡覺。

所以我的問題是:什么是同步這些線程的好方法,以實現之前描述的所需行為,但同時以一種安全的死鎖方式?

根據您的評論,聽起來像CyclicBarrier完全符合您的需求。 從文檔(強調我的):

一種同步輔助工具, 允許一組線程全部等待彼此到達公共障礙點 CyclicBarriers在涉及固定大小的線程方的程序中很有用,這些線程必須偶爾等待彼此。 屏障稱為循環,因為它可以在等待線程釋放后重新使用

不幸的是,我自己沒有使用它們,所以我不能給你具體的指示。 我認為基本的想法是使用帶有barrierAction的雙參數構造函數構造barrierAction 完成此任務后,在此屏障上有n線程await() ,之后執行barrierAction ,之后n線程將繼續。

來自CyclicBarrier#await()的javadoc:

如果當前線程是要到達的最后一個線程,並且在構造函數中提供了非null屏障操作,則當前線程在允許其他線程繼續之前運行該操作。 如果在屏障操作期間發生異常,則該異常將在當前線程中傳播,並且屏障處於斷開狀態。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM