2016-04-06 21 views
1

現在、セマフォだけのスレッドセーフなスレッドプールを実装する必要がある教育用の課題に取り組んでいます。セマフォ実装のプロデューサ - コンシューマ指向のスレッドプール

SynchronizewaitnotifysleepなどのスレッドセーフなAPIは使用しないでください。私が持っているコードにすぎ取得せずに、まず

  • はスレッドセーフなキュー(ない2つのスレッドが同時に\デキューをキューイングすることはできません)(私はConcurrentLinkedQueueで、この問題をテストしていると実装

    共有:

      問題が

    設計自体)持続します

  • Tasksセマフォ= 0

  • Availableセマフォ= 0

  • Tasks_Queueキュー

  • Available_Queueキュー

ワーカースレッド:

  • Blockedセマフォ= 0

一般情報:

  • のみマネージャ(シングルスレッド)Tasks_QueueAvailable_Queue

  • のみのApp-メイン(シングルスレッド)をデキューできるタスクをキューに入れることができていますTasks_Queue

  • 各ワーカースレッドは、 Available_Queue

だから我々は、単一のプロデューサー、単一マネージャーといくつかの消費者が混在しています。

  • アプリが最初に起動し、すぐにAvailable_Queue自体をエンキューますワーカースレッドのそれぞれを開始すると、Availableセマフォを解放し、それが個人的なBlockedセマフォの取得ブロックされます。
  • たびのApp-主マネージャは、それが最初の両方TasksAvailableセマフォを取得しなければならない新しいタスクを実行したいときはいつでも、それはTaskセマフォ
  • を解放し、新しいタスクをキューに入れます。

私の質問:アプリケーションの実行時に

セマフォは、使用可能なワーカースレッドが存在しないことが知られているとき、キューへのアクセスを保護するために設置されていても、ヌルの労働者を返すdequeue_worker()機能を。

ヌルスレッドを描画する場合、再帰的にdequeue_worker()を呼び出して問題を解決しましたが、セマフォーの許可を永久に失うことを想定しています。しかし、私が労働者の数を1に制限すると、労働者は永遠にブロックされません。

1)オリジナルデザインのブレークポイントは何ですか?

2)私の "ソリューション"がデザインをさらに壊すことはありませんか?

コードスニペット:

// only gets called by Worker threads: enqueue_worker(this); 
    private void enqueue_worker(Worker worker) { 
     available_queue.add(worker); 
     available.release(); 
    } 

// only gets called by App-Main (a single thread) 
    public void enqueue_task(Query query) { 
     tasks_queue.add(query); 
     tasks.release(); 
    } 

// only gets called by Manager(a single Thread) 
    private Worker dequeue_worker() { 
     Worker worker = null; 
     try { 
      available.acquire(); 
      worker = available_queue.poll(); 
     } catch (InterruptedException e) { 
      // shouldn't happen 
     } // **** the solution: **** 
     if (worker==null) worker = dequeue_worker(); // TODO: find out why 
     return worker; 
    } 

// only gets called by Manager(a single Thread) 
    private Query dequeue_task() { 
     Query query = null; 
     try { 
      tasks.acquire(); 
      query = tasks_queue.poll(); 
     } catch (InterruptedException e) { 
      // shouldn't happen 
     } 
     return query; 
    } 

// gets called by Manager (a single thread) 
    private void execute() { // check if task is available and executes it 
     Worker worker = dequeue_worker(); // available.down() 
     Query query = dequeue_task(); //task.down() 
     worker.setData(query); 
     worker.blocked.release(); 
    } 

そして最後に労働者Run()方法:あなたがメインループでenqueue_worker、二時間に1回、2回available.release()を呼び出している

while (true) { // main infinite loop 

       enqueue_worker(this); 
       acquire(); // blocked.acquire(); 
       <C.S> 
       available.release(); 
      } 

答えて

3

+0

スレッドセーフではありません。私のブロック機構は 'Available'と' Tasks'セマフォを使って実装されています –

+0

あなたの再帰的反復は同じですが、非常に非効率的です – hoaz

+0

availlable.acquire()呼び出しはnullオブジェクトの.poll() 。 –

関連する問題