概述
内核当发生访问资源冲突的时候,可以有两种锁的解决方案选择:
• 一个是原地等待(自旋锁方式)
• 一个是挂起当前进程,调度其他进程执行(睡眠)(互斥锁方式)
Spinlock 是内核中提供的一种比较常见的锁机制,自旋锁是“原地等待”的方式解决资源冲突的,即,一个线程获取了一个自旋锁后,另外一个线程期望获取该自旋锁,获取不到,只能够原地“打转”(忙等待)。由于自旋锁的这个忙等待的特性,注定了它使用场景上的限制 —— 自旋锁不应该被长时间的持有(消耗 CPU 资源)。
在 linux kernel 的实现中,经常会遇到这样的场景:共享数据被中断上下文和进程上下文访问,该如何保护呢?如果只有进程上下文的访问,那么可以考虑使用 semaphore 或者 mutex 的锁机制,但是现在中断上下文也参和进来,那些可以导致睡眠的 lock 就不能使用了,这时候,可以考虑使用 spin lock。换言之,中断上下文要用锁,首选 spinlock。自旋锁尽可能的减少线程的阻塞,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起再唤醒的操作的消耗,这些操作会导致线程发生两次上下文切换!
初始化自旋锁(pthread_spin_init)
头文件:
#include <pthread.h>
函数原型:
int pthread_spin_init(pthread_spinlock_t *lock int pshared);
作用:
初始化自旋锁 lock
参数含义:
lock:自旋锁
pshared:要设置的自旋锁属性,为 PTHREAD_PROCESS_PRIVATE 表示互斥锁只能在本进程中使用,为 PTHREAD_PROCESS_SHARED 表示互斥锁可以在不同进程间使用
返回值:
成功返回 0,
失败返回错误码
销毁自旋锁(pthread_spin_destory)
头文件:
#include <pthread.h>
函数原型:
int pthread_spin_destory(pthread_spinlock_t *lock);
作用:
销毁自旋锁 lock
参数含义:
lock:自旋锁
返回值:
成功返回 0,
失败返回错误码
获取自旋锁
一直获取(pthread_spin_lock)
头文件:
#include <pthread.h>
函数原型:
int pthread_spin_lock(pthread_spinlock_t *lock);
作用:
获取自旋锁 lock 并上锁,没获取到则一直循环获取
参数含义:
lock:要获取的自旋锁
返回值:
成功返回 0
失败返回错误码
直接返回的获取(pthread_spin_trylock)
头文件:
#include <pthread.h>
函数原型:
int pthread_spin_trylock(pthread_spinlock_t *lock);
作用:
获取自旋锁 lock 并上锁,没获取到则立即返回
参数含义:
lock:要获取的自旋锁
返回值:
成功返回 0
失败返回其他值
解锁操作(pthread_spin_unlock)
头文件:
#include <pthread.h>
函数原型:
int pthread_spin_unlock(pthread_spinlock_t *lock);
作用:
释放自旋锁 lock(解锁)
参数含义:
lock:要释放的自旋锁
返回值:
成功返回 0
失败返回其他值