【二】10.L并发与竞争机制
前言:
L是一个多任务(线程)的操作系统,会存在多任务共同操作同一段内存或者设备的情况,多任务甚至中断都能访问的资源叫做共享资源,需要保护起来。
1.并发产生的原因:并发就是多个“用户”(线程)同时访问同一个共享资源。
(1)多线程并发访问,L是多任务(线程)的系统,所以多线程访问是最基本的原因。
(2)抢占式并发访问,也就说调度程序可以任意时刻抢占正在运行的线程,从而运行其他的线程。
(3)中断程序并发访问。
(4)SMP(多核)核间并发访问。
2.L中处理并发带来的竞争:
(1)原子操作:一般用于整型变量或者位操作,指不能再进一步分割的操作。
<1>整型变量的原子操作:


<2>位操作的原子操作:

(2)自旋锁:当一个线程要访问共享资源时应先获取自旋锁,锁只能被一个线程持有,只要此线程不是放持有的锁,那么其他的线程就不能获取此锁。 未能获得锁的线程会一直等待锁可用且线程不会进入休眠状态或去做其他处理。这也是自选锁的缺点,因而自旋锁适用短时期的轻量级加锁。


<1>自旋锁引起线程间死锁: 自旋锁 API 函数适用于 SMP 或支持抢占的单 CPU 下线程之间的并发访问,也就是用于线程与线程之间,被自旋锁保护的临界区一定不能调用任何能够引起睡眠和阻塞的API 函数,否则的话会可能会导致死锁现象的发生。自旋锁会自动禁止抢占,也就说当线程 A得到锁以后会暂时禁止内核抢占。如果线程 A 在持有锁期间进入了休眠状态,那么线程 A 会自动放弃 CPU 使用权。线程 B 开始运行,线程 B 也想要获取锁,但是此时锁被 A 线程持有,而且内核抢占还被禁止了!线程 B 无法被调度出去,那么线程 A 就无法运行,锁也就无法释放,好了,死锁发生了!
<2>自旋锁引起线程和中断间死锁: 当中断也要使用自旋锁时,在线程中获取锁的时候关闭本地中断,防止中断抢占CPU后却又得不到锁而出现死锁的情况。


<3>自旋锁使用注意事项: 1.由于自旋锁特性,因此锁的持有时间不能太长,否则会降低系统性能。
2.自旋锁的保护区不饿能调用任何可导致线程休眠的API,因为自旋锁会禁止抢占,则会导致死锁。
3.不能递归申请自旋锁,否则会把自己锁死。
4.编写驱动时尽可能以多核角度去思考。
(3)信号量:信号量会使线程进入休眠状态,后会切换线程,因此有一下特点:
<1>可以使等待资源的线程进入休眠状态,因此适用于占用资源比较久的场合。
<2>不能用于中断中,因为中断不可休眠。
<3>不适合占用资源比较短的场合,因为切换线程开销很大。



(4)互斥体:
<1>、mutex 可以导致休眠,因此不能在中断中使用 mutex,中断中只能使用自旋锁。
<2>、和信号量一样, mutex 保护的临界区可以调用引起阻塞的 API 函数。
<3>、因为一次只有一个线程可以持有 mutex ,因此,必须由 mutex 的持有者释放 mutex 。并且 mutex 不能递归上锁和解锁。

