前書き
この記事は12番目の記事であるスレッド同期のスピンロックです。前回の記事では、ミューテックスを紹介し、ミューテックスを介したスレッド同期の問題を解決しました。この記事は、スレッドの同期を解決する別の方法です-スピンロック
スピンロック
スピンロックの動作原理はミューテックスとまったく同じですが、重要なリソースにアクセスする前にロックを追加し、完了後にロックを解放します。しかし、ミューテックスとスピンロックの間にはまだ少し違いがあります
- スピンロックはマルチスレッド同期の変数でもあります
- スピンロックを使用するスレッドは、ロック変数が使用可能かどうかを繰り返しチェックし、使用できない場合は繰り返しチェックします。
- したがって、スピンロックはCPUを放棄せず、ビジー待機状態になります。
つまり、スピンロックは実際には次のようになります。ロックが解放されるのを待つ無限ループ
スピンロックの利点
- スピンロックは、プロセスまたはスレッドのコンテキスト切り替えのオーバーヘッドを回避します(ロックに時間がかからない場合でも、コストは低くなります)
- オペレーティングシステム内の多くの場所で、ミューテックスの代わりにスピンロックが使用されています
- スピンロックはシングルコアCPUの使用には適していません(スピンロックは待機中にCPUを解放しないため、シングルコアCPUで使用すると、他のプロセスまたはスレッドの実行に失敗します)
スピンロックとミューテックス(ロック)の比較
- スピンロックは非ブロッキングロックです。つまり、スレッドがスピンロックを取得する必要があるが、ロックがすでに他のスレッドによって占有されている場合、スレッドは中断されませんが、CPU時間を消費し続けます。スピンロックを取得するには
- ミューテックスはブロッキングロックです。スレッドがミューテックスを取得できない場合、スレッドは直接中断されます。スレッドはCPU時間を消費しなくなります。他のスレッドがミューテックスを解放すると、オペレーティングシステムは中断されたものをアクティブにします。スレッド、配置します。運用開始
2種類のロック適用シナリオ
- マルチコアプロセッサの場合、スレッドがロックを待機する時間が非常に短く、スレッドのコンテキスト切り替え時間が2回より短いと予想される場合は、スピンを使用する方が費用効果が高くなります。ロック
- マルチコアプロセッサの場合、スレッドがロックを長時間、少なくとも2つのスレッドコンテキストスイッチの時間よりも長く待機することが予想される場合は、ミューテックスを使用することをお勧めします。
- シングルコアプロセッサの場合は、通常、スピンロックを使用しないことをお勧めします。同時に実行状態にあるスレッドは1つしかないため、実行中のスレッドがロックを取得できないことがわかった場合、ロックが解除されるのを待つことしかできませんが、中断されていないため、ロックを取得したスレッドには実行状態に入る方法。実行中のスレッドがオペレーティングシステムによって割り当てられたタイムスライスを使い果たした場合にのみ、スケジュールを設定する機会があります。この場合、スピンロックを使用するコストは非常に高くなります
提案:ロックコードが頻繁に呼び出されるが、競合がほとんど発生しない場合は、スピンロックを優先する必要があります。スピンロックのオーバーヘッドは比較的小さく、ミューテックスのオーバーヘッドは大きくなります。
スピンロックのコード例
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
$include<vector>
//自旋锁定义
pthread_spinlock_t spin_lock;
//临界资源
int num=0;
//生产者
void *producer(void*){
int times = 100000000;//循环一百万次
while(times--){
//加自旋锁
pthread_spin_lock(&spin_lock);
num += 1;//每次生产一个产品
//解锁
pthread_spin_unlock(&spin_lock);
}
}
//消费者
void *consumer(void*){
int times = 100000000;
while(times--){
//加自旋锁
pthread_spin_lock(&spin_lock);
num -= 1;//每次消费一个产品
//解锁
pthread_spin_unlock(&spin_lock);
}
}
int main()
{
printf("Start in main function.");
//初始化自旋锁
pthread_spin_init(&spin_lock, 0);
//定义两个线程
pthread_t thread1,thread2;
//一个执行生成者逻辑,一个执行消费者逻辑
pthread_create(&thread1, NULL, &producer, NULL);
pthread_create(&thread2, NULL, &consumer, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
//打印临界资源的值
printf("Print in main function: num = %d\n", num);
return 0;
}
の結果
急速に変化するテクノロジーの常識を見つけることは、技術者のコアコンピタンスです。理論と実践を組み合わせた知識と行動の統一