seegongsik
操作系统

什么是竞态条件

两个人在同一刻改同一样东西,结果就可能出错。办法是一个一个地轮着改。

01

两个人改同一格

墙上贴着一张写着数字的便条,现在是 10。两个人都想在上面加 1。
一个人看到 10,在脑子里算出 11,再在便条上写下 11。另一个人也照样做。可要是两个人几乎同时开始,两人看到的都是最初的 10,写下的也都是 11。
加了两次 1,本该是 12,结果却是 11。有一次加法凭空消失了,这是在同一刻改同一样东西闹出的事故。
像浏览量、账户余额这种许多人一起改的数字,一旦出这种事故,一次变化就会悄无声息地丢掉。

10AB读 10读 10111111写 11写 11本该12却11少了一次

两个人同时改同一个值,加上的其中一次就会消失。

在同一刻改同一样东西,结果就可能出错。

02

同样的动作,不同的结果

两个一模一样的人,同样各加 1,这次只改变时机看看。
按顺序来:一个人看到 10,写下 11,做完之后,另一个人看到那个 11,写下 12。结果是 12,对了。
交叠着来:一个人读到 10,还没写,另一个人也读到了 10。两人都写下 11,结果是 11,错了。
动作一字不差,完全一样。决定对错的,只是什么时候插进来这一个时机。
所以这类问题十次里有九次好好的,偶尔才错一次,特别难抓。

轮着来A 读10B 读11写11写1212对撞着来A 读10B 读1011错

同样是加法,按顺序就对,交叠就错。

决定结果的不是动作,而是什么时候插进来的时机。

03

亲手让它们交叠

两个干活的各往同一个值上加 1。亲手调一调,两人开始的时间交叠多少。
隔得足够开,一个人全做完了另一个人才开始,结果就对。挨得太近,一个人还没写,另一个人就读了,一次加法就没了。
拖动滑块,找找从哪一点开始结果出错。同样的两个动作,一交叠,结果就垮了。
哪怕只交叠一点点,也可能丢掉一次,所以光指望时机别撞上,并不是真正的解决办法。

读改写A读改写B
12结果对
重叠20%
拉开就对,是12,撞上就错,成了11。自己找找从哪儿开始变红。

改一改交叠的程度,看看从什么时候开始结果出错。

把两人隔开,结果就对;交叠得越多,出错的风险越大。

04

一个一个轮着来

那该怎么防?答案很简单:在改同一样东西的时候,只让一个人碰它。
一个人读、改、写的时候,另一个人等着。这一整套做完了,下一个人才开始。就像排队上单人卫生间:里面有人,门就锁上;出来了,下一个人才能进去。
这样就不会交叠,结果总是对的。代价是会有等待的时间:为了安全,接受短暂的排队。
关键是把读、改、写三个动作捆成一体来守住。要是只挡住写的那一刻,却让读敞开着,漏洞就又出现了。

12A使用中B等着一个一个,不撞代价是等待

改同一样东西的时候只让一个人碰,其余的人排队等着。

让大家一个一个轮着改同一样东西,交叠就消失了,结果也就安全了。

05

用一张纸总结

只要记住三点。
第一,在同一刻改同一样东西就会出事故:就像两人同时加时会丢掉一次一样,结果可能出错。
第二,问题不在动作,而在时机:同样的事,按顺序做就对,交叠就错。第三,一个一个轮着来就安全:改同一样东西的时候只让一个人碰,其余的人排队等,结果就总是对的。
好几个人一起用某样东西、事情又同时发生的时候,顺序不会自己守住,得由我们来定。

一
同一个瞬间改同一样东西会出事故。两人同时加就少一次。
二
问题不在动作,在时机。轮着来就对,撞一块就错。
三
一个一个来就安全。只许一个人动,其余排队,结果就总是对的。

同时 + 共用就出事故,问题在时机,一个一个来才安全。

一句话总结同时改同一样东西,结果就可能出错;让大家一个一个轮着来,就能防住。
← 操作系统
如果有帮助,请支持我们