iOS 原理探究-自旋锁

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

单核CPU不适于使用自旋锁,这里的单核CPU指的是单核单线程的CPU,因为,在同一时间只有一个线程是处在运行状态,假设运行线程A发现无法获取锁,只能等待解锁,但因为A自身不挂起,所以那个持有锁的线程B没有办法进入运行状态,只能等到操作系统分给A的时间片用完,才能有机会被调度。这种情况下使用自旋锁的代价很高。

获取、释放自旋锁,实际上是读写自旋锁的存储内存或寄存器。因此这种读写操作必须是原子的。

忙等

以下的C语言程序示例,两个线程共享一个全局变量i,第一个线程用忙碌等待来确认变量i的值是否有改变。

#include 
#include 
#include 
​
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;
}

你可能感兴趣的:(iOS 原理探究-自旋锁)