セマフォで保護された、スレッド間で共有する必要のある配列があります。次のように、初期化コードを複数回呼び出すことができる関数「コンストラクター」内に配置しました。
#include <stdbool.h> //for bool
#include <semaphore.h>
sem_t global_mutex;
char global_array[N]; // Protected with global_mutex
struct my_struct *new_my_struct(){
static bool is_init = false; // This will be initialized only once, right?
if (!is_init){ // 1
sem_init(&global_mutex, 0, 1); // 2
sem_wait(&global_mutex); // 3
if (!is_init){ // 4
is_init = true; // 5
... initialize global_array ... // 6
}
sem_post(&global_mutex); // 7
}
... proceed on the create and return a my_struct pointer ...
}
理想的な世界では、スレッドは1から7まで実行され、配列を初期化してクリティカル領域を終了します。別のスレッドが2で停止した場合でも、4のテストはfalseになり、配列は上書きされません。スレッドが1でスタックし、セマフォを再初期化した場合にどうなるかについてはあまり考えていませんが、最初に実行するスレッドによってtrueに設定されている限り、それほど問題にはならないと思います。is_init
ここで、スレッドが4で停止し、別のスレッドが開始から完了まで実行され、初期化と入力が行われる場合、競合状態が発生しますglobal_array
。スレッドが4回の実行で停止すると、配列が再初期化され、最初のスレッドによって保存された状態が削除されます。
その競合状態に悩まされない方法があるかどうか(おそらくstatic
?の巧妙な使用)、または並行性がないときに初期化コードをコンストラクターから分離してメインスレッドで使用する必要があるかどうかを知りたいです。
このコードは使用中であり、まだ競合状態に悩まされていません。しかし、その可能性はわかっているので、修正したいと思います。