pthread_cond_waitおよびpthread_cond_signalでのイールドの保証
-
10-07-2019 - |
質問
グローバル変数、ミューテックス、条件変数を共有する3つのPOSIXスレッドを持つCプログラムがあると仮定します。そのうちの2つは次の擬似コードを実行しています:
...process data...
pthread_mutex_lock( &mutex );
variable = data_ptr;
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );
3回目の実行:
while(1) {
while( variable == NULL ) {
pthread_mutex_wait( &cond, &mutex );
}
printf( "Data is %d", *variable );
}
3番目のスレッドが最初の2つのそれぞれのデータを見ると想定しても安全ですか?
別の方法で、スレッドがミューテックスと条件変数で待機している場合、他のスレッドではなく、シグナルが送信された場合にロックを取得する次のものと想定しても安全ですか?ロックを待っていますか?
解決
pthread_mutex_waitのようなものはありません。私はあなたが意味すると仮定します:
pthread_mutex_lock(&mutex);
/* ... */
while (1) {
while (variable == NULL)
pthread_cond_wait(&cond, &mutex);
printf("Data is %d", *variable);
}
/* ... */
pthread_mutex_unlock(&mutex);
3番目のスレッドが両方からのデータを見るという保証はありません。 pthread_cond_signalは3番目のスレッドを呼び起こしますが、すぐにmutexを取得しない場合があります。他のライターの1人が最初にミューテックスを使用する場合があります。ただし、もう少し作業を行うと、目的を達成できます。
void put(int *p) {
pthread_mutex_lock(&mutex);
while (variable)
pthread_cond_wait(&cond_empty, &mutex);
variable = p;
pthread_cond_signal(&cond_full);
pthread_mutex_unlock(&mutex);
}
int *get() {
int *ret;
pthread_mutex_lock(&mutex);
while (!variable)
pthread_cond_wait(&cond_full, &mutex);
ret = variable;
variable = NULL;
pthread_cond_signal(&cond_empty);
pthread_mutex_unlock(&mutex);
return ret;
}
変数の読み取りを明示的に待機することにより、潜在的な競合状態を回避します。
他のヒント
標準で見つけたものは次のとおりです。
4.13スケジューリングポリシー
スケジューリングポリシーはプロセスまたはスレッドの順序に影響します:
[...]
- プロセスまたはスレッドがブロックされたスレッドであり、実行可能なスレッドになる場合
準拠する実装では、各スケジューリングポリシーが優先順位を変更するか、上記の各オカレンスでプロセスまたはスレッドの順序に影響を与える方法を定義します。さらに、準拠する実装は、他のどのような状況で、各スケジューリングポリシーが優先順位を変更したり、プロセスやスレッドの順序に影響を与えたりする可能性があるかを定義します。
したがって、明らかに未定義です。驚くべきことではありません。一般的に言えば、どの実行可能スレッドの実行がスケジュールされるかについては何も想定できません。
pthread_cond_wait
マンページによると
ブロックされていないスレッドは、スケジューリングポリシー(該当する場合)に従って、それぞれが
pthread_mutex_lock
()を呼び出したかのように、mutexを争います。
残念ながら、私が知る限り、希望する動作を提供する利用可能なスケジューリングポリシーはありません。