并发和竞态

来源:互联网 发布:安卓模拟器mac版玩崩坏 编辑:程序博客网 时间:2024/05/17 02:18

1.        竞态通常是作为对资源的共享访问而产生的。

2.        当两个执行线程需要访问相同的数据结构(或硬件资源)时,混合的可能性就永远存在。

如何避免共享的方法:

A、只要可能,应该尽量避免资源的共享。如果没有并发访问,也就不会有竞态的产生。这种思想的最明显应用就是避免全局变量的使用。

B、在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,因此必须显示的管理对该资源的访问。访问管理的最常见技术称为“锁定”或者“互斥”确保一次只有一个执行线程可操作共享资源

C、当内核代码创建一个可能和其它内核部分共享的对象时,该对象必选在还有其它组件引用自己时保持存在(并正确工作)。在这一规则下产生两个需求:在对象尚不能正确工作时,不能将其对内核可用,也就是说,对这类对象的应用必须得到跟踪。

3.        PV

希望进入临界区的进程将在相关信号量上设置P;如果信号量的值大于零,则该值会减小一,而进程可以继续。相反,如果信号量的值为零或更小,进程必须等待,直到其他人释放该信号量。对信号量的解锁通过调用V函数来完成;该函数增加信号量的值,并在必要时唤醒等待的进程。

当信号量用于互斥时,即避免多个进程同时在一个临界区中运行,信号量的值应该初始化为1.

 

4.        信号量的实现

直接创建信号量

void sema_initstruct semaphore *sem, int val

其中val是赋予一个信号量的初始值

 

信号量统称被用于互斥体(信号量的值为1),静态声明和初始化一个互斥

DECLEAR_MUTEXname       //val = 1

DECLEAR_MUTEX_LOCKEDname //val = 0

 

如果互斥体必须在运行时被初始化,则使用下面的函数之一,动态分配互斥

void init_MUTEXstruct semaphore *sem

void init_MUTEX_LOCKEDstruct semaphore *sem

 

P函数down的三个版本:

void downstruct semaphore *sem      

int down_interruptiblestruct semaphore *sem                   //操作是个中断的(信号中断)

int down_trylockstruct semaphore *sem                            //永远不会休眠,如果信号量在调用时不可获得信号量,将立即返回一个非零值。

down_interruptible如果被中断,函数的返回值非零,而调用者不会拥有该信号量。所以要对其检查返回值,并做出相应的响应。

V函数up:

void upstruct semaphore *sem

调用up之后,调用者不再拥有该信号量。

   

down_interruptible使用举例:

if(down_interruptible(sem))

          return ERESTARTSYS;

代码中检查down_interruptible的返回值。如果它返回非零值,则说明操作被中断。这种情况下,通常要做的工作是返回-ERESTARTSYS。在见到这个返回代码后,内核的高层代码要么会从头重新启动该调用,要么会将该错误返回给用户。如果我们返回-ERESTARTSYS,则必须首先撤销已经做出的任何用户可见的修改,这样系统调用可正确重试。如果无法撤销这些操作,则应该返回-EINTR

 

 5.         completion

关于completionLDD3中举了一个例子并且有一段长长的描述来告诉我们completionsemaphore在某些情况下更加有效率。但是很可惜,无论英文还是中文 我均为读懂。

还是把这段描述抄下来吧:

在通常的使用中,试图锁定某个信号量的代码会发现该信号量几乎总是可用;而如果存在针对该信号量的严重竞争,性能将受到影响,这时,我们需要重新审视锁定机制。因此,信号量对“可用”情况已经做了大量优化。然而,如果像上面那样使用信号量在任务完成时进行通信,则调用down的线程几乎总是要等待,这样性能也同样会受到影响。如果信号量在这种情况下声明为自动变量,则也可能受某个(难对付的)竞态的影响。在某些情况下,信号量可能在调用up的进程完成其相关任务前消失。(什么玩意!!)

 

静态创建completion:

DECLARE_COMPLETION(my_completion);

动态创建completion

init_completion(&my_completion);

等待completion

wait_for_completion(struct completion *c);

该函数执行一个非中断的等待。如果代码调用了wait_for_completion且没有人会完成该任务,则将产生一个不可杀的进程。

原创粉丝点击