1、并发和竞态
并发( concurrency )指的是多个执行单元同时、并行被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态( race conditions )
解决竞态问题的途径是保证对共享资源的互斥访问,互斥访问就是指一个执行单元在访问共享资源时其他的执行单元都被禁止访问。
访问共享资源的代码区称临界区,临界区需要用互斥机制加以保护。中断屏蔽,原子操作,自旋锁和信号量。
自旋锁:
1、只有两种状态:锁定和解锁;
2、自旋锁会让线程一直原地等待,查询是否可以访问这个共享资源。所以自旋锁只适合短期持有,自旋锁时间如果过长会浪费处理器时间,降低系统性能。
信号量:
信号量与自旋锁不同的是信号量会告诉你还需要等待多久。
区别:
1、信号量的进程在等待锁从新变为可用时会睡眠,适用于锁被长期占用的情况;
2、执行线程在锁被征用时会睡眠,只能在进程上下文中才能获取信号量锁,因为在中断上下文中(使用自旋锁)是不能被调度的。
3、进程可以在持用信号量时去睡眠,当其他进程需要获得同一信号量是不会产生死锁,占用信号量时是不能再持有自旋锁的,因为占用信号量可能会导致睡眠,但是自旋锁不允许睡眠;
4、信号量锁保护的临界区可能包含引起阻塞的代码,自旋锁要绝对避免这样的临界区,因为阻塞意味着要进行进程的切换,若进程被切换出去后,另一进程企图获取本自旋锁就会发生死锁;
5、信号量不同于自旋锁,不会禁止内核抢占(自旋锁被持有时,内核不能被抢占),所以持有信号量的代码可以被抢占,也就是说信号量不会对调度的等待时间带来影响;
自旋锁和信号量可以睡眠吗?
自旋锁不能睡眠,信号量可以睡眠;
自旋锁禁止cpu抢占,而信号量不禁止cpu抢占
自旋锁在锁住以后如果进入睡眠,由于不能进行处理器抢占,其他系统进程都不能获得CPU而运行,所以不能唤醒睡眠的自旋锁。系统就不能响应任何操作。
信号量在临界区睡眠以后,其他进程可以用抢占的方式继续运行。
自旋锁和信号量可以用在中断中?
信号量不能用在中断中,信号量会引起睡眠,中断不能睡眠;
自旋锁也可以用于中断,在获取锁之前一定要先禁止本地中断(也就是本CPU中断),否则会锁死;
读写锁:
读写锁是指临界区的一个文件可以同时读取,但是不能同时发生读和写。
读写自旋锁是允许对临界区的共享资源进行并发读操作,但是不允许多个线程并发读写操作。