互斥量的工作原理
如果有多個線程同時通路臨界資源,互斥量保證臨界資源是被串行通路的。某個線程通路臨界資源,線程首先給臨界資源加鎖,加鎖好其他資源無法通路,其他線程隻能等目前線程解鎖後才能使用。
自旋鎖
作業系統提供的API:
pthread_spinlock_t自旋鎖的工作原理與互斥量一摸一樣,也是在使用前加鎖,使用完解鎖保證串行通路。
自旋鎖也是一種多線程同步的變量,使用了自旋鎖的線程會反複的檢查鎖變量是否可用。如果不可用,就會一直循環的檢查。是以自旋鎖不會讓出CPU,是一種忙等待狀态。是死循環等待鎖被釋放。自旋鎖的優缺點
- 避免了程序或線程的上下文開銷,如果鎖占用時間不長,使用自旋鎖代價很小
- 作業系統内部很多地方使用自旋鎖
- 不适合在單核CPU使用,因為他等待時不會釋放CPU,而是死循環等待。
生産者消費者模型
#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 = 10000000;
while (times--) {
pthread_spin_lock(&spin_lock);
num += 1;
pthread_spin_unlock(&spin_lock);
}
}
void *comsumer(void *) {
int times = 10000000;
while (times--) {
pthread_spin_lock(&spin_lock);
num -= 1;
pthread_spin_unlock(&spin_lock);
}
}
int main() {
pthread_spin_init(&spin_lock, 0);
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, &producer, NULL);
pthread_create(&thread2, NULL, &comsumer, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("臨界資源:%d",num)
return 0;
}
不會讓出cpu的demo,讓消費者sleep10秒,生産者的自旋鎖将會循環等待,檢視此時的程序CPU是否為100%。
#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 = 10000000;
while (times--) {
pthread_spin_lock(&spin_lock);
num += 1;
pthread_spin_unlock(&spin_lock);
}
}
void *comsumer(void *) {
int times = 10000000;
while (times--) {
pthread_spin_lock(&spin_lock);
num -= 1;
sleep(10);
pthread_spin_unlock(&spin_lock);
}
}
int main() {
pthread_spin_init(&spin_lock, 0);
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, &producer, NULL);
pthread_create(&thread2, NULL, &comsumer, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("臨界資源: %d\n", num);
return 0;
}
備注:
代碼中使用的是POSIX标準提供的程式設計接口,mac是沒有的,是以在Mac下測試自旋鎖是會出現報錯的。下圖是Linux下已程序形式測試自旋鎖cpp,可以看到spin_lock所使用的程序接近百分之百,說明自旋鎖在運作的時候并不會讓出CPU。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPnJma01mYoR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2cTMxQjMyUDM1ATOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
圖檔來源慕課網:《變成必備基礎》