マルチスレッド
pthread_cond_*系でスレッド同期をするという話。
演習のときはかなりテンパってたけど、サンプルコード無視して、
manしたほうが早かったという話。
というわけで解説
マルチスレッドにおけるモニタとは、セマフォよりも複雑だけど、欠点を克服したパターンらしい。
まぁ良く知らんけど。
とにかく、UNIX系システムコールで実装する上でポイントとなる点を列挙してみる。
ポイント
- モニタ用ロック1つ(pthread_mutex)を使って、モニタメソッドの呼び出しを整列する。
- 任意の数のスレッド同期用の状態記録オブジェクト(pthread_cond)を用意し、これを伝書鳩に使う。
- 状態の変更を通知するにはpthread_cond_broadcastを用いる。
- 状態の変更を待つには、状態をwhileの条件に書き、内部でpthread_cond_waitを使う。
解説
ポイントの番号と対応してる。
- モニタ用のロックは1つだけ。これによって、モニタメソッドを複数のスレッドが同時に実行することを防ぐ。(Javaのsynchronize)
- 今回は箸が5本あるので、pthread_condも5個用意する。箸には使用の可否と、待ち状態の二つの変数が対応付けられているが、どちらもpthread_cond一つで対処している。相手先のwhileの条件がfalseなら、もう一度スリープに入るから問題ない。
- pthread_cond_broadcastによって、pthread_cond_waitの部分でスリープしていたスレッドが動き出す。待っている相手が唯一と保証できるならpthread_cond_signalを使える。通知は状態が変化したのが判明してから、それ以降任意のタイミングで良いと思われる。
- pthread_cond_waitにモニタ用ロックを同時に渡すことで、実行したスレッドはスリープに入り、ロックを開放する。これによって他のスレッドがモニタを実行できるようになる。スレッドのウェイクは、pthread_cond_broadcastによって行われる。
サンプルコード(待つ部分、通知する部分のみ)
bool hage=true; //ハゲてる。 pthread_cond_t condition; monitor_wait() { pthread_mutex_lock(&lock); // 生えるのを待つ。 while(hage==true){ // lockを渡すことで、スリープしたときはロックが解除される。 pthread_cond_wait(&condition, &lock); } // 生えた! printf("I got hair!\n"); pthread_mutex_unlock(&lock); } monitor_notify() { pthread_mutex_lock(&lock); ... //ここで状態が変わる。 hage=false; // 生えた。 pthread_cond_broadcast(&condition); // これによりmonitor_waitが起きる。 ... pthread_mutex_unlock(&lock); }