8

2 人のワーカーがいるとします。各ワーカーには と の ID が0あり1ます。また、常にジョブが到着すると仮定します。各ジョブには、このジョブを実行する必要があるワーカーを指定する識別子0もあります。1

最初はロックされている 2 つのスレッドを作成し、2 つのジョブが到着したらロックを解除し、それぞれのジョブを実行してから、他のジョブが到着するまで再度ロックします。

次のコードがあります。

  #include <iostream>
  #include <thread>
  #include <mutex>

  using namespace std;

  struct job{

      thread jobThread;
      mutex jobMutex;

  };

  job jobs[2];


  void executeJob(int worker){

      while(true){

          jobs[worker].jobMutex.lock();

          //do some job

      }

   }

  void initialize(){

      int i;
      for(i=0;i<2;i++){
                jobs[i].jobThread = thread(executeJob, i);
      }

   }

  int main(void){

      //initialization
      initialize();

      int buffer[2];
      int bufferSize = 0;

      while(true){
          //jobs arrive here constantly, 
            //once the buffer becomes full, 
            //we unlock the threads(workers) and they start working
          bufferSize = 2;
          if(bufferSize == 2){
              for(int i = 0; i<2; i++){
                  jobs[i].jobMutex.unlock();
              }
          }
           break;
     }

  }

数日前に使い始めましstd::threadたが、理由はわかりませんが、Visual Studio でabort() has been called. 何かが足りないと思いますが、私の無知のため、何が足りないのかわかりません。

このコードが実際に

  1. 2 つのスレッドを初期化してからロックする

  2. メイン関数内で 2 つのスレッドのロックを解除すると、2 つのスレッドはそれぞれの仕事を行い (この場合は何もしません)、その後再びロックされます。

しかし、代わりにエラーが発生します。私は何を間違っていますか?

前もって感謝します!

4

3 に答える 3

9

この目的のために、boost のスレッドプール クラスを使用できます。それは効率的で、十分にテストされています。あなたが新しく書いて安定させる代わりに、オープンソースライブラリ。

http://threadpool.sourceforge.net/

main()
{
    pool tp(2);   //number of worker threads-currently its 2.

    // Add some tasks to the pool.
    tp.schedule(&first_task);
    tp.schedule(&second_task);
}

void first_task()
{
    ...
}

void second_task()
{
    ...
}

ノート:

例の提案: スレッドごとに個別のミューテックス オブジェクトを用意する必要はありません。単一ミューテックス オブジェクト ロック自体が、すべてのスレッド間の同期を行います。executejob 関数で 1 つのスレッドのミューテックスをロックしていて、ロックを解除せずに別のスレッドが別のミューテックス オブジェクトでロックを呼び出しているため、デッドロックまたは未定義の動作が発生します。

また、ロックを解除せずにwhileloop内でmutex.lock()を呼び出しているため、同じスレッドが同じmutexオブジェクトで自分自身をロックしようとしており、未定義の動作が無限に発生します。

スレッドを並行して実行する必要がない場合は、executejob 関数内で 1 つのグローバル ミューテックス オブジェクトを使用して、ロックとロック解除を行うことができます。

mutex m;

void executeJob(int worker)
{
    m.lock();

    //do some job

    m.unlock();
}

ジョブを並行して実行したい場合は、以前に提案したようにブースト スレッドプールを使用します。

于 2013-04-12T17:02:56.193 に答える