私は pthreads にまったく慣れていません。私が見たすべてのサイトには、不必要な情報がたくさんあるようです。
私は 2 つの関数を持っています。今のところ X と Y と呼びましょう。これらは両方ともメモリ内のブロックで動作します。1 つのスレッドが XI を実行している場合、他のスレッドが同じブロックで X または Y を呼び出したくない場合、これが決して起こらないようにするにはどうすればよいですか?
特定のブロック値の関数をミューテックス ロックする必要がありますか?
ミューテックスを使用する必要があります。
コードをロックするのではなく、データをロックする必要があります。ブロックごとにミューテックスを作成し、関数がブロックで動作している間はロックし、終了したらロックを解除します。
ミューテックスは、pthread.h、pthread_mutex_t で定義されるタイプです。ミューテックスをロックおよびロック解除する関数が提供されます。これらの関数は、一度に 1 つのスレッドのみがロックを取得できることを保証します (ブロックが使用されていることを示すために変数を使用しただけの場合、ブロックではなくその変数で同時実行の問題が発生します)。
オンラインで利用できるチュートリアルは多数あります。Google の「pthread チュートリアル」を参照してください。
リソース (この場合はメモリ ブロック) をミューテックスでロックします。または、そのメモリ領域を読み取り/更新する関数コードの部分だけをロックすることもできます。これはクリティカル セクションと呼ばれ、コーディングには別のアプローチが必要です。これは、スレッドがリソースと対話する部分にヒットした場合を除いて、スレッドが自由に動作できることを意味します。
最初の方法は実装が簡単です。関数 X または Y 全体に対するオール オア ナッシング アプローチです。
おそらく、いくつかのデモンストレーション コードが適切です。次のようなブロックヘッダーがあると仮定します。
struct block {
void *data;
size_t len;
};
この構造体にミューテックス変数を追加して、ブロックを保護します。
struct block {
void *data;
size_t len;
pthread_mutex_t lock;
};
次に、この構造体の初期化関数を更新して、ロックを初期化する必要があります。
struct block *new_block(size_t len)
{
struct block *b = malloc(sizeof *b);
b->data = malloc(len);
b->len = len;
pthread_mutex_init(&b->lock, NULL);
return b;
}
X 関数と Y 関数 (およびブロックに対して読み取りまたは書き込みを行うその他の関数) は、ロックを取得し、終了時に解放する必要があります。
int x(struct block *b)
{
int retval;
pthread_mutex_lock(&b->lock);
/* code */
pthread_mutex_unlock(&b->lock);
return retval;
}
int y(struct block *b)
{
int retval;
pthread_mutex_lock(&b->lock);
/* code */
pthread_mutex_unlock(&b->lock);
return retval;
}
エラー リターン パスでもミューテックスのロックを解除するように注意する必要があります。
マルチスレッド プログラミングは、より高水準の言語を使用することで、より適切に解決されます。C では理解しにくいことがいくつかありますが、私の意見では、マルチスレッドもその 1 つです。Java を使用すると、問題や問題をよりよく理解できることがわかりました。概念を理解しやすく、ドキュメントを読みやすくなっています。Java が得意でない場合は、Poco や Qt などの C++ フレームワークも適しています。
他の人が言ったように、概念的にはリソースをロックしたいと考えています(あなたの場合はメモリのセクション)。セマフォは、概念として、この問題にミューテックスよりもはるかに適しています。私はセマフォを研究し、ミューテックスをセマフォの構成要素と考えています。私に言わせれば、ミューテックスは名前の悪いバイナリ セマフォです。