由于自旋锁不会睡眠,自旋锁一直占用cpu,在未获得锁的情况下,一直运行,所以占用着cpu,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低。因此,自旋锁通常用于驱动程序开发中,适合对短暂处理的资源进行加锁。
注意:在单处理器环境下,我们是不需要自旋锁,尽管调用了自旋锁的函数,里面也不是自旋锁的实现。
Linux系统中提供了如下几个函数来操作自旋锁:
函数 | 作用 |
---|---|
pthread_spin_init | 初始化一个自旋锁 |
pthread_spin_destroy | 注销一个自旋锁 |
pthread_spin_lock | 加锁操作,如果不成功,则阻塞等待 |
pthread_spin_trylock | 测试加锁,如果不成功则立刻返回 |
pthread_spin_unlock | 解锁操作 |
需要的头文件:
#include
函数格式:
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
** 参数说明:
lock:自旋锁变量;
pshared:自旋锁属性
常见属性见下表;
属性值 | 意义 |
---|---|
PTHREAD_PROCESS_SHARED | 该自旋锁可以在多个进程中的线程之间共享 |
PTHREAD_PROCESS_PRIVATE | 仅初始化本自旋锁的线程所在的进程内的线程才能够使用该自旋锁 |
函数返回值说明: 调用成功,返回值总为0,否则返回一个非零的错误码。
对自旋锁初始化后,就可以给自旋锁进行加锁操作。Linux提供了两个库函数来对加锁,分别是:pthread_spin_lock和pthread_spin_trylock,这些函数的具体的说明如下:
需要的头文件:
#include
函数格式:
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
参数说明:
lock:要被执行加锁操作的锁变量
函数返回值说明:
调用成功,返回值为0,否则,返回一个非零的错误码。
pthread_spin_lock和pthread_spin_trylock区别:
用pthread_spin_lock加锁时,如果lock已经被锁住,当前尝试加锁的线程就会被阻塞,直到自旋锁被其他线程释放。而pthread_spin_trylock函数则不同,如果lock已经被锁住,它将立即返回,返回的错误码为EBUSY,而不是阻塞等待。
需要的头文件如下:
#include
函数格式如下:
int pthread_spin_unlock(pthread_spinlock_t *lock);
参数说明:
lock:要被执行解锁操作的锁变量
函数返回值说明:
调用成功,返回值为0,否则返回一个非零的错误码。
需要的头文件如下:
#include
函数格式如下:
int pthread_spin_destroy(pthread_spinlock_t *lock);
参数说明:
lock:要被执行注销操作的锁变量
函数返回值说明:
调用成功,返回值为0,否则返回一个非零的错误码。
案例:
编写一个程序,使用自旋锁对一个全局变量进行加锁。详细代码如下所示:
#include
#include
int globalNumber = 1;
//初始化一个普通自旋锁number_lock
pthread_spinlock_t number_lock;
void *addNumer(void *arg)
{
pthread_spin_lock(&number_lock);
globalNumber++;
pthread_spin_unlock(&number_lock);
return NULL;
}
int main()
{
pthread_spin_init(&number_lock, PTHREAD_PROCESS_PRIVATE);
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, addNumer, NULL); //创建进程
pthread_create(&thread2, NULL, addNumer, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("globalNumber = %d\n", globalNumber);
pthread_spin_destroy(&number_lock);
return 0;
}
将以上代码保存为lockThread.c文件,编译执行。可以看到globalNumber变量变为了3,尽管我们不对globalNumber变量进行加锁,结果可能也是3,但是有可能出现结果为2的情况。