1. ミューテックス
同期: 秩序ある方法でリソースにアクセスします。相互排他: 常に 1 つのみが実行されますが、マルチスレッド プログラムの場合、アクセス競合の問題はよく発生します。解決策は、ミューテックス (Mutex、MutualExclusive Lock) を導入し、スレッドが完了できるようにすることです。 「読み取り - 変更 - 書き込み」操作を行った後、ロックを他のスレッドに解放します。このように、ロックを取得していないスレッドは待機することしかできませんが、共有データにアクセスすることはできません。 write" はアトミック操作を形成します。これらをすべて実行するか、まったく実行しないかのどちらでも、実行途中で中断されることはなく、この操作は他のプロセッサーで並行して実行されません。
ミューテックス ロックは、pthread_mutex_t 型の変数で表されます。 pthread_mutex_init で初期化され、hread_destroy() で破棄されます。成功した場合は 0 を返し、失敗した場合はエラー番号を返します。 。ミューテックス変数が静的に割り当てられている場合 (グローバル変数または静的変数)、マクロ定義 PTHREAD_MUTEX_INITIALIZER で初期化することもできます。これは、pthread_mutex_init で初期化するのと同じで、attr パラメーターが NULL です
スレッドは pthread_mutex_lock を呼び出してミューテックスを取得できます。 pthread_mutex_lock を呼び出してミューテックスを取得した後、現在のスレッドはハングして、別のスレッドが pthread_mutex_unlock を呼び出してミューテックスを解放するまで待機する必要があります。現在のスレッドはウェイクアップされてから、ミューテックスを取得して実行を続行できます。これは、スレッドがミューテックスをロックしているがロックを解除しておらず、別のスレッドがミューテックスを取得しようとしている場合、そのスレッドはハングアップして、ロックされたスレッドがミューテックスのロックを解除してミューテックスを解放するまで待つ必要があることを意味します。ミューテックスを取得します。
スレッドがロックを取得したいが、ハングして待機したくない場合は、pthread_mutex_trylock を呼び出すことができます。ミューテックスが別のスレッドによって取得されている場合、この関数は失敗し、スレッドをハングさせることなく EBUSY を返します。そして待ってください。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<pthread.h> 4 static int g_count=0; 5 void * addWrite(void * arg) 6 { 7 int count=0; 8 int value=0; 9 while(count++ <5000) 10 { 11 value=g_count; 12 printf("g_count is %d\n",g_count); 13 g_count=value+1; 14 } 15 } 16 int main() 17 { 18 pthread_t id1; 19 pthread_t id2; 20 int ret=pthread_create(&id1,NULL,addWrite,NULL); 21 int res=pthread_create(&id2,NULL,addWrite,NULL); 22 pthread_join(id1,NULL); 23 pthread_join(id2,NULL);
2 つのスレッドを作成し、それぞれ g_count を 5000 回増加させます。通常、最終的なカウンターは 10000 になるはずですが、実際にはプログラムを実行するたびに結果が異なります。5000 を超える場合もあれば、5000 までカウントされる場合もあります。 6000を超えていますが、ロックを追加した後、以下に示すように5行目(in)にpthread_mutex_initを追加します
ロックを追加すると、10000が出力されます
2番目、実装原理ロックとロック解除の実現のために、ほとんどのアーキテクチャはスワップ命令または交換命令を提供します。この命令の機能は、命令が 1 つしかないため、アトミック性が保証されています。マルチプロセッサ プラットフォームでは、アクセス メモリ バス サイクルにもシーケンスがあります。あるプロセッサ上のスワップ命令が実行されると、別のプロセッサ上のスワップ命令はバス サイクルを待つことしかできません。これを以下の疑似コードに示します。ロック解除のロック解除操作も、アトミック性を確保するために 1 つの命令のみで実装されます。
3. デッドロック
・通常、同じスレッドが lock を 2 回呼び出した場合、2 回目の呼び出しでは、ロックがすでに占有されているため、スレッドはハングし、他のスレッドがロックを解放するのを待ちます。スレッドが単独で占有され、ロックを解放する機会がないままサスペンドされるため、常にサスペンド待ちの状態になります。これをデッドロックといいます。もう 1 つの典型的なデッドロック状況は次のとおりです。スレッド A がロック 1 を取得し、スレッド B がロック 2 を取得します。このとき、スレッド A はロックを呼び出してロック 2 を取得しようとします。その結果、スレッド A はハングしてスレッド B が解放されるまで待つ必要があります。ロック 2、およびこれ スレッド B もロック 1 を取得しようとして lock を呼び出すと、スレッド A がロック 1 を解放するまで待機する必要があるため、スレッド A と B は両方とも永久にサスペンド状態になります。
デッドロック形成の条件
②. リクエストと保持の条件: リソースの要求によりプロセスがブロックされた場合、取得したリソースは保持されます。
③. 非剥奪条件: プロセスによって取得されたリソースは、使い果たされる前に強制的に剥奪することはできません。
④循環待機状態: 複数のプロセス間で先頭から末尾までの循環待機リソース関係が形成されます
より多くのスレッドとより多くのロックが関与すると、デッドロックの問題が発生する可能性が高くなります。プログラムを作成するときは、必要に応じて複数のロックを同時に取得しないようにする必要があります。原則として、すべてのスレッドが複数のロックを必要とする場合は、同じ順序に従う必要があります (最も一般的なのは、 Mutex変数のアドレス順) ロックが取れていればデッドロックは発生しません。たとえば、ロック 1、ロック 2、およびロック 3 がプログラムで使用されており、それらに対応する Mutex 変数のアドレスがロック 1
上記は Linux スレッドの同期と相互排他に関する内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。