Linux并发与竞争
- 实现共享资源的互斥访问,也是为了实现共享资源的按照我们预期的方式进行修改。
- 需要保护的不是代码,而是数据!数据!数据!某个线程的局部变量不需要保护,我们要保护的是多个线程都会访问的共享数据。
-
实现Linux并发与竞争的方式:
-
原子操作
- Linux 内核定义了叫做 atomic_t 的结构体来完成整形数据的原子操作,在使用中用原子变量来代替整形变量,此结构体定义在 include/linux/types.h
- 2.原子操作只能对整形变量或者位进行保护。
-
自旋锁
- 1.自旋锁的“自旋”也就是“原地打转”的意思,“原地打转”的目的是为了等待自旋锁可以用,可以访问共享资源。即一直等待。
- 2.自旋锁适用于短时期的轻量级加锁。
- 3.因为自旋锁的特性:那就等待自旋锁的线程会一直处于自选状态,线程本身会因为满足不了条件不能处理事情,但是也不会让出CPU,其他的线程也不能占用CPU。这样在自旋这段时间,浪费处理器时间,降低系统性能,所以自旋锁的持有时间不能太长。
- 4.自旋锁API函数适用于SMP或支持抢占的单CPU下线程之间的并发访问,也就是用于线程与线程之间.
- 5.被自旋锁保护的临界区一定不能调用任何能够引起睡眠和阻塞的API 函数,否则的话会可能会导致死锁现象的发生。
- 6.读写锁
- 7.顺序锁
-
信号量
- 1.因为信号量使线程进入休眠状态以后会切换线程,切换线程就会有开销.
- 2.因为信号量可以使等待资源线程进入休眠状态,因此适用于那些占用资源比较久的场合.
- 3.如果共享资源的持有时间比较短,那就不适合使用信号量了,因为频繁的休眠、切换线程引起的开销要远大于信号量带来的那点优势。
- 4.因此信号量不能用于中断中,因为信号量会引起休眠,中断不能休眠。
-
互斥体
- 1.互斥访问表示一次只有一个线程可以访问共享资源,不能递归申请互斥体。
- 2.mutex 可以导致休眠,因此不能在中断中使用 mutex,中断中只能使用自旋锁。
- 3.和信号量一样, mutex 保护的临界区可以调用引起阻塞的 API 函数。
- 4.因为一次只有一个线程可以持有 mutex,因此,必须由 mutex 的持有者释放 mutex。并且 mutex 不能递归上锁和解锁。
-