【发布时间】:2011-01-29 18:58:09
【问题描述】:
请有人简单地告诉我临界区的含义是什么?用简单的语言
【问题讨论】:
-
请不要 LMGTFY,这很粗鲁。
标签: multithreading terminology
请有人简单地告诉我临界区的含义是什么?用简单的语言
【问题讨论】:
标签: multithreading terminology
critical section 是一段代码,需要在没有外部干扰的情况下执行 - 即没有另一个线程可能影响/受该段内“中间”状态的影响。
例如,预订系统在预订某物时可能有一个关键部分,即它需要检查该项目是否可用,然后将其标记为不再可用,而无需其他尝试预订房间来改变这一点中间状态。
因此,一段代码的关键部分是一次只允许一个执行线程的地方,以防止出现竞争条件等情况。
【讨论】:
临界区是一段代码,如果多个线程同时执行此操作,它们可能会相互干扰,从而导致不正确的结果或其他故障。想象一个用于处理支票的简单银行例程:
doCheck (writer, recipient, amount) {
if (amount < 0) return DIAF;
balance = getBalance( writer );
if (balance < amount) return NSF;
setBalance( recipient, getBalance(recipient) + amount );
setBalance( writer, balance - amount );
}
现在假设我的余额是 11,000 美元,我开了两张支票:
John, ColumbiaHouse, $0.01
John, MrsJohn, $10,000
现在我们的银行处理了如此多的检查,以至于“王牌”程序员 DonaldJavaSlump 添加了线程,因为性能 - 但他不知道关键部分,所以线程 1 开始处理第一个检查:
if (amount < 0) return DIAF; // (0.01 < 0)? OK
balance = getBalance(John) // $11,000
if (balance < amount) return NSF; // (11,000 < 0.01?) OK
setBalance( ColumbiaHouse, ... // KaChing! ColumbiaHouse gets paid
现在线程 2 从处理第二次检查的同一段代码开始:
if (amount < 0) return DIAF; // (10,000 < 0)? OK
balance = getBalance( John ); // $11,000 (still!)
if (balance < amount) return NSF; // (11,000 < 10,000?) OK
setBalance( MrsJohn, ... // KaChing! MrsJohn gets paid
setBalance( John, balance - amount ); // my balance is now $1,000 :(
然后线程 1 开始完成它的工作:
setBalance( John, balance - amount ); // now balance is $10,999.99!!! :)
现在 John 和 MrsJohn 更加高兴了,可以带着免费的钱去游轮了!!
【讨论】:
关键部分包含修改共享数据的代码部分。监视器确保一次只有一个线程进入。
【讨论】:
临界区例程是解决两个或多个程序同时竞争相同资源问题的一种方法。想象一下,两个程序想要增加一个计数器。如果两者同时进行:获取操作数,将其递增,然后存储回递增的值,则其中一个增量将丢失。在当今的处理器上,程序可以使用原子读-修改-写指令,例如获取和操作、比较和交换或交换。在早期的处理器上,这些指令是不存在的。问题是仅使用普通的汇编程序指令以原子方式完成递增。这个问题是由 Edsgar Dijkstra 定义并首先解决的。 “关键部分例程”是他对解决问题的代码的名称。
【讨论】: