互斥与同步
一 并发
1.并发: 是指可能导致对共享资源的访问出现竞争状态的若干执行路径,不一定是时间上的。
2.并发的来源
2.1中断处理路径
2.2调度器的可抢占性(单处理器的特性,导致进程与进程指间的并发)
2.3多处理器的并发执行
3.临界区
对共享资源进行访问的代码片段成为临界区。
二 自旋锁
在多处理器系统中提供对共享数据的保护,其背后核心思想是:设置一个多处理器指间的共享全局变量V,并定义V=1时,上锁状态;V=0,解锁状态。如果处理器A要进入临界区,则首先要读取V值,若V != 0,则表示有其他处理器正在访问共享数据,此时A处理器处于等待状态,即自旋状态;若V=0,表示没有其他处理器访问共享数据,此时A可以访问共享数据,先将V设置为1,即上锁,然后进入临界区,访问完毕离开时将V置0,即解锁。(原子操作)
spin_lock(spinlock_t *lock)
三 信号量(semaphore)
相当于自旋锁,其最大的特点是允许调用它的线程进入睡眠状态。
信号量主要是down和up操作。当count > 0,则表示当前线程可以获得信号量;就将count减1,然后退出;挡count不大于0,表示当前线程不可得到信号量,最终调用__down_common。这种情况下,count = 1,也就是说任一时刻只允许一个进程进入临界区,此时linux提供了一个宏来定义、初始化,DECLEAR_MUTEX。
四 互斥锁
count = 1的信号量实现互斥方法不是linux经典方法,linux对count = 1的信号量情况重新定义一个新的数据结构struct mutex
小结:
自旋锁不会引起睡眠,因而最适合在不允许睡眠的上下文环境执行,比如中断处理函数。
互斥锁的实现来源于信号量,如果一个进程在进入临界区前视图调用互斥锁,可能会进入休眠状态,所以在中断上下文中严禁使用互斥锁和信号量。