2017-07-27 1 views
1

私はセマフォの使用方法を示す簡単なプログラムを書いています。 (そしてカスタムがセマフォーの作業を書いたかどうかをテストするために)。Pocoマルチスレッドを使用する際にセマフォを使用して順序を保証するにはどうすればよいですか?

私は4つのスレッドが同時に機能を実行しています。各機能は無作為に待機し、次に印刷します。Hello, world! This is threadnI slept foruSuS

期待どおり、メッセージはランダムな順序で標準出力に出力されます。これは、スレッドが順番に実行されている場合に順番に表示されるため、同時に実行されていることを示しています。

このデモンストレーションでは、セマフォを使用して強制的に注文したいと考えています。しかし、現在は動作しません。ここで

は私のコードです:

sem = sem_open("mutex" , O_CREAT | O_RDWR , S_IRWXU | S_IRWXG | S_IRWXO, 1); // name, oflag, mode, initial value 

Poco::Thread thread[5]; 

class HelloRunnable: public Poco::Runnable 
{ 
public: 
    HelloRunnable(int arg) //constructor for the runnable 
    { 
     n = arg; 
    } 

    int n; 

    virtual void run() //entry point for the threads 
    { 
     sem_wait(sem); //the semaphore 
      timeval t; 
      gettimeofday(&t, NULL); 
      srand(t.tv_usec * t.tv_sec); 
      int uS = rand()%100000; 
      usleep(uS); //sleep for random length of time 

      std::cout << "Hello, world! This is thread " << n << " I slept for "<< uS << "uS" <<std::endl; 
     sem_post(sem); 
     return; 
    } 
}; 



int main() 
{ 
    HelloRunnable runnable1(1); //construct a runnable with arg = 1 
    thread[1].start(runnable1); //execute that runnable 

    HelloRunnable runnable2(2); //construct a runnable with arg = 2 
    thread[2].start(runnable2); //execute that runnable 

    HelloRunnable runnable3(3); //... 
    thread[3].start(runnable3); 

    HelloRunnable runnable4(4); 
    thread[4].start(runnable4); 

    //wait for all threads to finish 
    thread[1].join(); 
    thread[2].join(); 
    thread[3].join(); 
    thread[4].join(); 

    return 0; 
} 

しかし、スレッドはまだランダムな順序でメッセージを標準出力に出力します。例えば:それはメッセージが順序で印刷されることを保証するよう

//Hello, world! This is thread 2 I slept for 15001uS 
//Hello, world! This is thread 1 I slept for 51124uS 
//Hello, world! This is thread 4 I slept for 60884uS 
//Hello, world! This is thread 3 I slept for 86137uS 

はどこのコードで私は、セマフォを置く必要がありますか?これが簡単な場合にはお詫び申し上げます。私はコーディングの背景から来ていません。私はちょうどusleep前にsem_waitを移動

EDIT

。今はより良く機能しますが、すべてではありません。それは時間の約45%の順序で、逆の順序では約45%、ランダムな順序では約10%の時間で印刷されます。どうしてこれなの!?

答えて

0

sem_waitでブロックされたスレッドは、予期しない順序で起動されるためです。さらに、無秩序な睡眠時間を追加して無秩序を増やします。

実際、スレッドごとに1つのセマフォーが必要です。 スレッドNsem_postセマフォN + 1次いでsem_waitセマフォNべきです。 最終スレッドsem_postセマフォなどが必要です。 1つの配列にセマフォを作成するだけで、最初の値は初期値1で、もう1つは0になります。thread引数はスレッド内の正しいセマフォにアクセスするためのインデックスにすることができます。

#include <Poco/Thread.h> 

#include <iostream> 

#include <semaphore.h> 
#include <sys/time.h> 
#include <unistd.h> 

#define THREADS 5 
#define LOOPS 5 

sem_t semaphores[THREADS]; 

class HelloRunnable: public Poco::Runnable { 
public: 
    HelloRunnable(unsigned int index) { 
     _index = index; 
     // Seed random generator 
     timeval time; 
     gettimeofday(&time, NULL); 
     srand(time.tv_usec * time.tv_sec); 
    } 

    virtual void run() { 
     for (unsigned int loop = 0; loop < LOOPS; ++loop) { 
      // Wait 
      sem_wait(&semaphores[_index]); 
      // Sleep random time 
      int sleep = rand() % 100000; 
      usleep(sleep); 
      // Output 
      std::cout << "Hello, world! This is thread " << _index 
        << " in loop " << loop << " I slept for " << sleep << "µS" 
        << std::endl; 
      // Unlock next thread 
      sem_post(&semaphores[(_index + 1) % THREADS]); 
     } 
     return; 
    } 
private: 
    unsigned int _index; 
}; 

int main() { 
    HelloRunnable *runnables[THREADS]; 
    Poco::Thread *threads[THREADS]; 

    // Initialize semaphores and create threads and runnables 
    for (unsigned int index = 0; index < THREADS; ++index) { 
     sem_init(&semaphores[index], 0, index ? 0 : 1); 
     threads[index] = new Poco::Thread(); 
     runnables[index] = new HelloRunnable(index); 
    } 

    // Start threads 
    for (unsigned int index = 0; index < THREADS; ++index) { 
     threads[index]->start(*runnables[index]); 
    } 

    // Wait for all threads to finish 
    for (unsigned int index = 0; index < THREADS; ++index) { 
     threads[index]->join(); 
    } 

    // Cleanup 
    for (unsigned int index = 0; index < THREADS; ++index) { 
     free(runnables[index]); 
     free(threads[index]); 
    } 
    return 0; 
} 
関連する問題