スレッドが一般的にどのように機能するかについて、多少混乱しているようです。
実際には、thread_func()
作成したさまざまなスレッド間で共有されることはありません。各スレッドには独自のコンテキストがあります。それらのすべてが実行中であってもthread_func()
、すべてがローカルである限り、それらのいずれも他の計算を台無しにしません。
同時アクセスについて心配する必要がある唯一のケースは、共有データ (グローバル変数など) の場合です。この場合、通常はミューテックスまたはセマフォを使用します。について読んでpthread_mutex_t
、sem_t
更新:と が何であるかを正確に指定していないため、それらはローカル変数であると想定しましたt
。i
それらがグローバルである場合、ミューテックスを使用してこれらの変数へのアクセスを同期する必要があります。t
またはのような意味のない名前でグローバル変数を呼び出すことi
は、一般的に悪い習慣であることに注意してください。
更新 2:あなたの編集により、あなたが本当に望んでいるものを理解できました。現時点で考えられる唯一の解決策は、t
すべてのスレッドに対して機能するグローバル変数を用意する必要があるということです。と呼びましょうstep
。step
すべてのスレッドがそれを読み取り、現在の反復が何であるかを知ることができるため、グローバルです。ただし、この変数への同時アクセスを調整するには、前述のようにミューテックスが必要です。
基本的なレイアウトは次のようになります。スレッドは、そのコンテキスト内で実行された最後の反復を格納します。step
別のスレッドによって更新されたかどうかを確認するために繰り返しテストしています。それが起こると、for
ループの実行を開始します (ループのi = start; ...
実行後、スレッドはそれがこの反復の最後のループであるかどうかをテストする必要があります。そうである場合は、グローバル値をインクリメントする必要がありますstep
(このとき、の新しい値を待ってスタックしていたスレッドはすべてstep
前進します)。
私たちが最後のスレッドであるかどうかをテストすることは、作成したスレッドの数を何らかの形で知っていることを意味します。これをパラメーターとして渡すか、定数として定義できます。として定義されていると仮定しTHREADS_NO
ます。
結果として、現在の反復を終了したスレッドの数を知るために、グローバル カウンターとミューテックスも必要になります。
したがって、ファイルは次のようになります。
pthread_mutex_t step_mutex;
pthread_mutex_t counter_mutex;
int step;
int counter;
void* thread_func(void* a) {
int t, i, curr_t;
struct type *b = (struct type*)a;
int start = b->start;
int stop = b->stop;
t = -1;
curr_t = 0;
while (1) {
while (curr_t == t) {
/* Wait for the next step */
pthread_mutex_lock(&step_mutex);
curr_t = step;
pthread_mutex_unlock(&step_mutex);
}
/* New value for t arrived */
t = curr_t;
if (t >= 1000) {
break;
}
for (i = start; i < stop; i++) {
/***** Calculation*****/
}
pthread_mutex_lock(&counter_mutex);
if (++counter == THREADS_NO) {
counter = 0;
pthread_mutex_lock(&step_mutex);
step++;
pthread_mutex_unlock(&step_mutex);
}
pthread_mutex_unlock(&counter_mutex);
}
return NULL;
}
おそらく でスレッドを作成する前に、両方のミューテックスを初期化する必要がありますmain()
。
pthread_mutex_init(&step_mutex, NULL);
pthread_mutex_init(&counter_mutex, NULL);
そして、仕事が終わったら、それらを破棄することを忘れないでください:
pthread_mutex_destroy(&step_mutex);
pthread_mutex_destroy(&counter_mutex);
エラーが発生する可能性があるため、ミューテックスを初期化、ロック、および破棄する関数の戻り値をテストする必要があることに注意してください。
最後に、これが本当に必要かどうかを検討してください。プログラムまたはアルゴリズムを再設計する必要があるかもしれません。このアプローチはあまり効率的ではありません。スレッドは新しい値を繰り返しテストするために CPU サイクルを浪費するからですstep
(これはビジー待機と呼ばれます)。「私たちはまだそこにいますか?私たちはまだそこにいますか?私たちはまだそこにいますか?」のようなものです...あまり賢くはありません。
注:このコードをテストできませんでした。あなたが投稿したコードは、何を達成しようとしているのかを知るのを少し難しくしているので、これが完全に機能するかどうかはわかりません.