并发:多个用户同时访问同一个资源
1.多线程并发访问
2.抢占式并发访问
3.中断程序并发访问
4.SMP(多核)核间并发访问
使用如下方式来实现对临界区的保护:
1.原子操作
主要用于对保护的数据是一个简单的整数或者简单位操作时用
typedef struct {
int counter;
} atomic_t;
atomic_t v = ATOMIC_INIT(0); //定义并初始化原子变零 v=0
atomic_set(10); //设置 v=10
atomic_read(&v); //读取 v 的值,肯定是 10
atomic_inc(&v); //v 的值加 1,v=11
2.自旋锁
等待自旋锁的线程会一直处于自旋状态,这样会浪费处理器时间,
降低系统性能,所以自旋锁适用于短时期的轻量级加锁
(被保护的临界区不能调用能够引起睡眠和阻塞的API函数)
spinlock_t lock; //自旋锁
spin_lock_init(&lock);
spin_lock_irqsave(&lock, flags) //获取锁
//临界区
spin_unlock_irqrestore(&lock, flags) //释放锁
其它:
读写自旋锁:一次只能允许一个写操作,没有写操作时可以进行多个读操作
顺序锁:实现同时读写,但是不能进行并发的写操作
3.信号量
计数型信号量,可以进行休眠,所以不能用在中断
struct semaphore sem;//定义信号量
sema_init(&sem, 1);//初始化信号量
down(&sem); //申请信号量
//临界区
up(&sem); //释放信号量
4.互斥体
一次只有一个线程可以访问共享资源,mutex不能递归上锁和解锁
struct mutex lock; //定义一个互斥体
mutex_init(&lock); //初始化互斥体
mutex_lock(&lock); //上锁
//临界区
mutex_unlock(&lock); //解锁