自旋锁是一种多线程同步机制,用于保护共享资源避免受并发访问的影响。
在多个线程尝试获取锁时,它们会持续自选(即在一个循环中不断检查锁是否可用)而不是立即进入休眠状态等待锁的释放。
这种机制减少了线程切换的开销,适用于短时间内锁的竞争情况。但是不合理的使用,可能会造成CPU的浪费。
自旋锁通常使用一个共享的标志位(如一个布尔值)来表示锁的状态。当标志位为true时,表示锁已经被某个线程占用;当标志位为false时,表示锁可用。当一个线程尝试获取自旋锁时,它会不断检查标志位:
大致流程:
自旋锁的实现通常使用原子操作来保证操作的原子性,常用的软件实现方式是通过CAS(Compare-And-Swap)指令实现。以下是一个简单的自旋锁实现示例(伪代码):
#include <stdio.h>
#include <stdatomic.h>
#include <pthread.h>
#include <unistd.h>
// 使用原子标志来模拟自旋锁
atomic_flag spinlock = ATOMIC_FLAG_INIT; // ATOMIC_FLAG_INIT 是 0
// 尝试获取锁
void spinlock_lock()
{
while (atomic_flag_test_and_set(&spinlock))
{
// 如果锁被占用,则忙等待
}
}
// 释放锁
void spinlock_unlock()
{
atomic_flag_clear(&spinlock);
}typedef _Atomic struct
{
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
_Bool __val;
#else
unsigned char __val;
#endif
} atomic_flag;Linux提供的自旋锁系统调用
#include <pthread.h>
int pthread_spin_lock(pthread_spinlock_t* lock);
int pthread_spin_trylock(pthread_spinlock_t* lock);
int pthread_spin_unlock(pthread_spinlock_t* lock);
int pthread_spin_init(pthread_spinlock_t* lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t* lock);注意:
自旋锁是一种适用于短时间内锁竞争情况的同步机制,它通过减少线程切换的开销来提高锁操作的效率。然而,它也存在CPU资源浪费和可能引起活锁等缺点。在使用自旋锁时,需要根据具体的应用场景进行选择,并确保锁被释放的时间尽可能短。
// 操作共享变量会有问题的售票系统代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 1000;
//pthread_spinlock_t lock;
void* route(void* arg)
{
char* id = (char*)arg;
while (1)
{
//pthread_spin_lock(&lock);
if (ticket > 0)
{
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
//pthread_spin_unlock(&lock);
}
else
{
//pthread_spin_unlock(&lock);
break;
}
}
return nullptr;
}
int main(void)
{
//pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, route, (void*)"thread 1");
pthread_create(&t2, NULL, route, (void*)"thread 2");
pthread_create(&t3, NULL, route, (void*)"thread 3");
pthread_create(&t4, NULL, route, (void*)"thread 4");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
//pthread_spin_destroy(&lock);
}感谢各位大佬支持!!!
互三啦!!!