并发和竞态
来源:互联网 发布:安卓模拟器mac版玩崩坏 编辑:程序博客网 时间:2024/05/17 02:18
1. 竞态通常是作为对资源的共享访问而产生的。
2. 当两个执行线程需要访问相同的数据结构(或硬件资源)时,混合的可能性就永远存在。
如何避免共享的方法:
A、只要可能,应该尽量避免资源的共享。如果没有并发访问,也就不会有竞态的产生。这种思想的最明显应用就是避免全局变量的使用。
B、在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,因此必须显示的管理对该资源的访问。访问管理的最常见技术称为“锁定”或者“互斥”— 确保一次只有一个执行线程可操作共享资源
C、当内核代码创建一个可能和其它内核部分共享的对象时,该对象必选在还有其它组件引用自己时保持存在(并正确工作)。在这一规则下产生两个需求:在对象尚不能正确工作时,不能将其对内核可用,也就是说,对这类对象的应用必须得到跟踪。
3. PV
希望进入临界区的进程将在相关信号量上设置P;如果信号量的值大于零,则该值会减小一,而进程可以继续。相反,如果信号量的值为零或更小,进程必须等待,直到其他人释放该信号量。对信号量的解锁通过调用V函数来完成;该函数增加信号量的值,并在必要时唤醒等待的进程。
当信号量用于互斥时,即避免多个进程同时在一个临界区中运行,信号量的值应该初始化为1.
4. 信号量的实现
直接创建信号量
void sema_init(struct semaphore *sem, int val)
其中val是赋予一个信号量的初始值
信号量统称被用于互斥体(信号量的值为1),静态声明和初始化一个互斥
DECLEAR_MUTEX(name) //val = 1
DECLEAR_MUTEX_LOCKED(name) //val = 0
如果互斥体必须在运行时被初始化,则使用下面的函数之一,动态分配互斥
void init_MUTEX(struct semaphore *sem)
void init_MUTEX_LOCKED(struct semaphore *sem)
P函数down的三个版本:
void down(struct semaphore *sem)
int down_interruptible(struct semaphore *sem) //操作是个中断的(信号中断)
int down_trylock(struct semaphore *sem) //永远不会休眠,如果信号量在调用时不可获得信号量,将立即返回一个非零值。
down_interruptible如果被中断,函数的返回值非零,而调用者不会拥有该信号量。所以要对其检查返回值,并做出相应的响应。
V函数up:
void up(struct semaphore *sem)
调用up之后,调用者不再拥有该信号量。
down_interruptible使用举例:
if(down_interruptible(sem))
return –ERESTARTSYS;
代码中检查down_interruptible的返回值。如果它返回非零值,则说明操作被中断。这种情况下,通常要做的工作是返回-ERESTARTSYS。在见到这个返回代码后,内核的高层代码要么会从头重新启动该调用,要么会将该错误返回给用户。如果我们返回-ERESTARTSYS,则必须首先撤销已经做出的任何用户可见的修改,这样系统调用可正确重试。如果无法撤销这些操作,则应该返回-EINTR。
5. completion 关于completion,LDD3中举了一个例子并且有一段长长的描述来告诉我们completion比semaphore在某些情况下更加有效率。但是很可惜,无论英文还是中文 我均为读懂。 还是把这段描述抄下来吧: 在通常的使用中,试图锁定某个信号量的代码会发现该信号量几乎总是可用;而如果存在针对该信号量的严重竞争,性能将受到影响,这时,我们需要重新审视锁定机制。因此,信号量对“可用”情况已经做了大量优化。然而,如果像上面那样使用信号量在任务完成时进行通信,则调用down的线程几乎总是要等待,这样性能也同样会受到影响。如果信号量在这种情况下声明为自动变量,则也可能受某个(难对付的)竞态的影响。在某些情况下,信号量可能在调用up的进程完成其相关任务前消失。(什么玩意!!) 静态创建completion: DECLARE_COMPLETION(my_completion); 动态创建completion init_completion(&my_completion); 等待completion wait_for_completion(struct completion *c); 该函数执行一个非中断的等待。如果代码调用了wait_for_completion且没有人会完成该任务,则将产生一个不可杀的进程。
- 并发和竞态
- 并发和竞态
- 并发和竞态
- 并发和竞态
- 并发和竞态
- 并发和竞态
- 并发和竞态
- 竞态和并发
- 并发和竞态
- 并发和竞态
- 并发和竞态控制
- 并发和竞态(理论篇)
- 并发和竞态(实践篇)
- 并发和竞态(理论篇)
- 并发和竞态(实践篇)
- Linux中的并发和竞态
- (LDD) 第五章、并发和竞态
- 第五章--并发和竞态
- 配置文件
- 弹出窗口函数MessageBox用法、分析及相应源代码(转帖)
- 从飞鸽传书口水仗想到的
- 工作分配问题
- 用PHP实现手机归属地查询api接口
- 并发和竞态
- kgfnxfg
- DirectX中Mesh的子集
- Converters from LaTeX to PC Textprocessors - Overview
- utuLinux内核定制编译全攻略
- 怎样把自己培养成为一个优秀的程序员
- log4j配置文件的例子
- 有用的文档
- 解决安装软件时的/usr/local/lib/libz.a(compress.o)错误