【发布时间】:2011-12-04 13:55:30
【问题描述】:
我想知道在上下文切换期间竞争条件将如何发生,以及发生的地点和方式。
我知道访问共享资源时可能会发生竞争条件,我只需要更好地理解它。有人可以帮我理解这个吗?
【问题讨论】:
标签: c++ operating-system linux-kernel
我想知道在上下文切换期间竞争条件将如何发生,以及发生的地点和方式。
我知道访问共享资源时可能会发生竞争条件,我只需要更好地理解它。有人可以帮我理解这个吗?
【问题讨论】:
标签: c++ operating-system linux-kernel
这是一个经典的例子:
int global_int = 0;
void update () {
++ global_int;
/* generated assembly is something like
register = global_int
increment register
global_int = register
*/
}
假设第一个线程开始运行,调用update(),但在第二条和第三条指令之间被中断(通过信号、上下文切换等)。现阶段global_int==0和register==1:还没有保存结果。
现在假设第二个线程运行update() 并完成,所以global_int==1。第一个线程恢复并将register(即1)保存到global_int,没有产生任何变化。
在这种情况下,global_int==1 在对update() 的两次 调用完成后。任何假设 update() 更新 global_int 的东西现在都将被破坏。
一般来说,非常很难通过查看代码发现这个问题,你必须分析数据 em> 对自己说“global_int 正在被不同的线程访问,我最好用互斥锁来保护它”。如果您尝试变得聪明并担心线程将如何访问它以避免花费锁定,那么您可能会弄错,除非在微不足道的情况下。
【讨论】:
竞争条件是并发执行代码访问共享资源的结果,但没有适当的机制来确保该共享资源的一致性。
如果线程调度程序的实现中存在错误,导致用于执行上下文切换的代码访问共享资源而没有提供适当的一致性保证,则可能会在上下文切换期间发生争用情况。没有任何关于实现上下文切换的代码使其无法包含竞争条件。
【讨论】:
假设您在单处理器机器上,其调度程序基本上对可用处理器的资源执行时间片(即,我们在一个非常简单的系统上)。然后假设您有一段代码的关键部分,但您没有使用互斥锁或其他同步原语保护该关键部分。
假设thread A 在临界区中。当thread A 的时间片结束时,调度程序会调度另一个thread B 并停止thread A。 Thread B 然后进入临界区(因为没有守卫),在临界区修改共享内存中的值。当thread B's 时间片启动时,操作系统会再次调度thread A,这会从它在临界区中停止的点继续。不过现在唯一的问题是 thread A 正在使用的值与上下文切换停止时的值不同……它们完全不同,因为它们是由 thread B 修改的。因此你有一个竞争条件。
【讨论】: