线程反复检查锁变量是否可用。由于线程在这一过程中保持执行, 因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释 放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很 短时间的场合是有效的。
单核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;
}
网友评论