線程反復檢查鎖變量是否可用。由于線程在這一過程中保持執行, 因此是一種忙等待。一旦獲取了自旋鎖,線程會一直保持該鎖,直至顯式釋 放自旋鎖。 自旋鎖避免了進程上下文的調度開銷,因此對于線程只會阻塞很 短時間的場合是有效的。
單核CPU不適于使用自旋鎖,這里的單核CPU指的是單核單線程的CPU,因為,在同一時間只有一個線程是處在運行狀態,假設運行線程A發現無法獲取鎖,只能等待解鎖,但因為A自身不掛起,所以那個持有鎖的線程B沒有辦法進入運行狀態,只能等到操作系統分給A的時間片用完,才能有機會被調度。這種情況下使用自旋鎖的代價很高。
獲取、釋放自旋鎖,實際上是讀寫自旋鎖的存儲內存或寄存器。因此這種讀寫操作必須是原子的。
忙等
以下的C語言程序示例,兩個線程共享一個全局變量i,第一個線程用忙碌等待來確認變量i的值是否有改變。
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
?
volatile int i = 0; /* i is global, so it is visible to all functions.
It's also marked volatile, because it
may change in a way which is not predictable by the compiler,
here from a different thread. */
?
/* f1 uses a spinlock to wait for i to change from 0\. */
static void *f1(void *p) {
while (i == 0) {
/* do nothing - just keep checking over and over */
}
printf("i's value has changed to %d.\n", i);
return NULL;
}
?
static void *f2(void *p) {
sleep(60); /* sleep for 60 seconds */
i = 99;
printf("t2 has changed the value of i to %d.\n", i);
return NULL;
}
?
int main() {
int rc;
pthread_t t1, t2;
rc = pthread_create(&t1, NULL, f1, NULL);
if (rc != 0) {
fprintf(stderr, "pthread f1 failed\n");
return EXIT_FAILURE;
}
rc = pthread_create(&t2, NULL, f2, NULL);
if (rc != 0) {
fprintf(stderr, "pthread f2 failed\n");
return EXIT_FAILURE;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
puts("All pthreads finished.");
return 0;
}