ホームページ  >  記事  >  システムチュートリアル  >  Linux の同期および相互排他メカニズム

Linux の同期および相互排他メカニズム

WBOY
WBOY転載
2024-03-18 13:49:10860ブラウズ

マルチプロセスまたはマルチスレッドのオペレーティング システム環境では、同期と相互排他は、共有リソースへの正しいアクセスを保証するために使用される重要な概念です。以下に、同期と相互排他、および相互排他に関する設計原則を示します。

Linux での実装:

同期

同期メカニズムは、複数の実行スレッドまたはプロセスの実行を調整して、それらが特定の順序で実行されるか、特定の条件下で待機するようにするプロセスです。一般的な同期メカニズムには、セマフォ、条件変数、バリアなどが含まれます。

Linux の同期および相互排他メカニズム

設計原則

  1. アトミック操作: アトミック操作とは、分割できない操作を指し、すべてが実行されるか、まったく実行されないかのいずれかです。同期では、アトミック操作はスレッドまたはプロセスの安全な実行を保証するために不可欠な要素です。

  2. 相互排他: 同期の主な目標は、共有リソースへの相互排他的アクセスを保証することです。つまり、競合状態を避けるために、共有リソースに同時にアクセスできるのは 1 つのスレッドまたはプロセスのみです。

  3. 条件待機: 同期メカニズムは通常、条件待機をサポートする必要があります。つまり、スレッドまたはプロセスは特定の条件が満たされるまで待機し、条件が満たされたときに他のスレッドまたはプロセスが待機中のスレッドに通知します。実行は継続してスレッド間の調整を実現します。

  4. 順序保持: 同期には、スレッドまたはプロセスが期待された順序で実行されることを保証するための実行順序の制御も含まれる場合があり、それによってプログラムの正確性と信頼性が保証されます。

Linux での実装

  • セマフォ: セマフォを通じてリソースをカウントし、限られた数のスレッドまたはプロセスのみが同時に共有リソースにアクセスできるようにすることができます。 Linux では、セマフォは通常、sem_initsem_waitsem_post などの関数を使用して操作されます。
  • 条件変数: 条件変数を使用すると、スレッドは特定の条件が満たされるまで待機し、条件が満たされたときに実行を続行するよう通知を受けることができます。 Linux では、条件変数は通常、pthread_cond_initpthread_cond_waitpthread_cond_signal などの関数を使用して操作されます。

ミューテックス(ミューテックス)

相互排他は、共有リソースへの相互排他的アクセスを保証するために使用されるメカニズムです。マルチスレッド環境またはマルチプロセス環境では、ミューテックス ロックが最も一般的な相互排他メカニズムです。

設計原則

  1. ミューテックス ロック: ミューテックス ロックは、1 つのスレッドだけが同時に共有リソースにアクセスできるようにするために使用されるロックです。 1 つのスレッドがミューテックス ロックを取得すると、他のスレッドは待機する必要があります。
  2. クリティカル セクション: クリティカル セクションは、共有リソースにアクセスする可能性のあるコードのセクションであり、同時に 1 つのスレッドのみが入ることができます。ミューテックス ロックは、重要なセクションを保護するためによく使用されます。
  3. デッドロックの回避: ミューテックス メカニズムを設計するときは、システムがミューテックス ロックの使用によって緩和されない待機状態に陥らないように、デッドロックの回避を考慮する必要があります。

Linux での実装

  • Mutex (ミューテックス): Linux では、通常、ミューテックス ロックは pthread_mutex_initpthread_mutex_lockpthread_mutex_unlock などの関数を通じて操作されます。これにより、スレッドが重要なセクションに安全に出入りできるようになります。
  • スピンロック: スピン ロックは、CPU を放棄せず、ミューテックス ロックを待機している間ループでチェックを続けるロックです。Linux では、スピン ロックは通常、spin_lock および spin_unlock を介して操作されます。

上記は、Linux で同期と相互排他を実現するための一般的なメカニズムの一部です。具体的な選択は、アプリケーションのニーズと、パフォーマンスと保守性の間のトレードオフによって異なります。

次のサンプル コードでは、ミューテックス (Mutex) と条件変数 (Condition Variable) を使用して、簡単な同期メカニズムを実装する方法を示します。ここでは、POSIX スレッド ライブラリの関連関数が使用されます。

####含む #含む #含む #define BUFFER_SIZE 5 int バッファ[BUFFER_SIZE]; int カウント = 0; pthread_mutex_t ミューテックス = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_Producer = PTHREAD_COND_INITIALIZER; pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER; void *プロデューサー(void *arg) { for (int i = 0; i while (count == BUFFER_SIZE) { // バッファーがいっぱいで、消費者による消費を待っています pthread_cond_wait(&cond_Producer, &mutex); } バッファ[カウント] = i; printf("生成されたもの: %d\n", i); // 消費者に消費できることを通知します pthread_cond_signal(&cond_consumer); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } void *consumer(void *arg) { for (int i = 0; i while (count == 0) { // バッファは空で、プロデューサーが生成するのを待っています pthread_cond_wait(&cond_consumer, &mutex); } int item = バッファ[--count]; printf("消費: %d\n", item); // 制作の準備ができたことをプロデューサーに通知します pthread_cond_signal(&cond_Producer); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } int main() { pthread_t プロデューサー スレッド、コンシューマー スレッド; //プロデューサーとコンシューマーのスレッドを作成する pthread_create(&Producer_thread, NULL, プロデューサー, NULL); pthread_create(&consumer_thread, NULL, Consumer, NULL); // スレッドが終了するまで待ちます pthread_join(プロデューサースレッド、NULL); pthread_join(consumer_thread, NULL); // ミューテックスロックと条件変数を破棄します pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond_Producer); pthread_cond_destroy(&cond_consumer); 0 を返します。 }
この簡単な例は、プロデューサー/コンシューマー問題を示しています。この問題では、プロデューサー スレッドがバッファーへのデータの生成を担当し、コンシューマー スレッドがバッファーからのデータの消費を担当します。ミューテックス ロック 

mutex は共有リソースへの排他的アクセスを保証するために使用され、条件変数 cond_Producer および cond_consumer はバッファーがいっぱいになるか待機するために使用されます。空と通知。

実際のアプリケーションにおける同期と相互排他はより複雑になる可能性があり、具体的な設計はアプリケーションのニーズに依存することに注意してください。

以下は、Linux で pthread_mutex_t を使用してミューテックス ロックを実装する方法を示す簡単なサンプル コードです。この例では、2 つのスレッドがカウンターを共有し、ミューテックス ロックによりカウンターへの相互排他的アクセスが保証されます。

####含む #含む // 共有カウンタ 整数カウンタ = 0; // ミューテックスロック pthread_mutex_t ミューテックス = PTHREAD_MUTEX_INITIALIZER; //スレッド関数、カウンタの値を増加します void* increment_counter(void* arg) { for (int i = 0; i main() { // スレッドを 2 つ作成します pthread_t スレッド 1、スレッド 2; pthread_create(&thread1, NULL, increment_counter, NULL); pthread_create(&thread2, NULL, increment_counter, NULL); // スレッドが終了するまで待ちます pthread_join(thread1, NULL); pthread_join(thread2, NULL); // ミューテックスロックを破棄します pthread_mutex_destroy(&mutex); // 最終的なカウンター値を出力する Printf("最終カウンター値: %d\n", counter); 0 を返します。 }
この例では、2 つのスレッドが 

counter 変数の値を同時にインクリメントします。両方のスレッドが同じ変数を共有するため、競合状態が存在します。ミューテックス ロック mutex は、counter への相互排他的アクセスを保証するために使用されます。1 つのスレッドは、counter にアクセスするときに最初にロックをロックし、完了後にロックを解除します。他のスレッドのスレッドが入る可能性があります。

ミューテックスロックを使用するには、次の点に注意する必要があります:

  1. ミューテックス ロックを初期化します: PTHREAD_MUTEX_INITIALIZER または pthread_mutex_init を使用して、ミューテックス ロックを初期化します。
  2. ロックとロック解除: ロックには pthread_mutex_lock を使用し、ロック解除には pthread_mutex_unlock を使用します。クリティカル セクション内の共有リソースへのアクセスは、ロックとロック解除の間に行う必要があります。
  3. ミューテックス ロックを破棄します: 不要になったミューテックス ロックを破棄するには、pthread_mutex_destroy を使用します。

上記のコードは、ミューテックス ロックを使用して共有リソースへの安全なアクセスを確保し、競合状態を防ぐ方法を示しています。

以上がLinux の同期および相互排他メカニズムの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlxlinux.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。