竞争条件(race condition)

在一些操作系统中,协作的进程可能共享一些彼此都能读写的公用存储区。这个公用存储区可能在内存中(可能是在内核数据结构中),也可能是一个共享文件。这里共享存储区的位置并不影响通信的本质及其带来的问题。为了理解实际中进程间通信如何工作,我们考虑一个简单但很普遍的例子:一个假脱机打印程序。当一个进程需要打印一个文件时,它将文件名放在一个特殊的假脱机目录 (spooler directory)下。另一个进程(打印机守护进程)则周期性地检查是否有文件需要打印,若有就打印并将该文件名从目录下删掉。

设想假脱机目录中有许多槽位,编号依次为0,1,2,…,每个槽位存放一个文件名。同时假设有两个共享变量:out,指向下一个要打印的文件;in,指向目录中下一个空闲槽位。可以把这两个变量保存在一个所有进程都能访问的文件中,该文件的长度为两个字。在某一时刻,0号至3号槽位空(其中的文件已经打印完毕),4号至6号槽位被占用(其中存有排好队列的要打印的文件名)。几乎在同一时刻,进程A和进程B都决定将一个文件排队打印,这种情况如图2-21所示。

在Murphy法则(任何可能出错的地方终将出错)生效时,可能发生以下的情况。进程A读到in的值为7,将7存在一个局部变量next_free_slot中。此时发生一次时钟中断,CPU认为进程A已运行了足够长的时间,决定切换到进程B。进程B也读取in,同样得到值为7,于是将7存在B的局部变量next_free_slot中。在这一时刻两个进程都认为下一个可用槽位是7。

进程B现在继续运行,它将其文件名存在槽位7中并将in的值更新为8。然后它离开,继续执行其他操作。

最后进程A接着从上次中断的地方再次运行。它检查变量next_free_slot,发现其值为7,于是将打印文件名存入7号槽位,这样就把进程B存在那里的文件名覆盖掉。然后它将next_free_slot加1,得到值为8,就将8存到in中。此时,假脱机目录内部是一致的,所以打印机守护进程发现不了任何错误,但进程B却永远得不到任何打印输出。类似这样的情况,即两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件(race condition)。调试包含有竞争条件的程序是一件很头痛的事。大多数的测试运行结果都很好,但在极少数情况下会发生一些无法解释的奇怪现象。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
竞态条件(race condition)和数据竞争(data race)是并发编程中常见的问题,它们可能会导致程序的不确定行为和错误结果。 竞态条件指的是多个并发操作在没有适当同步的情况下,对共享资源进行读写操作,从而导致结果的不确定性。具体来说,竞态条件发生在满足以下条件时: 1. 多个协程同时访问同一个共享资源。 2. 至少有一个协程对该共享资源进行写操作。 3. 对共享资源的访问没有适当的同步机制进行保护。 数据竞争是竞态条件的一种特殊情况,它指的是多个协程同时对同一个共享变量进行读写操作,且至少有一个协程进行写操作。数据竞争会导致未定义的行为,因为读写操作之间的顺序是不确定的,可能产生意外结果。 数据竞争可能导致以下问题: 1. 脏读(Dirty read):一个协程在另一个协程修改共享变量之前读取该变量的值,从而读取到了未完成的写操作的结果。 2. 竞态条件:多个协程通过竞争访问共享资源,导致结果的不确定性。 3. 无效的计算结果:由于数据竞争导致共享变量的值在不同协程之间不一致,可能会导致计算结果的错误。 为了避免竞态条件和数据竞争,需要使用合适的同步机制来保护共享资源,例如使用互斥锁、读写锁、通道等。同时,编写并发安全的代码也需要考虑避免共享资源的过度使用,尽量减少共享数据的需求。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值