我想知道在上下文切换期间将如何发生竞争条件,以及这种情况发生的位置和方式。
我知道访问共享资源时会出现竞争条件,我只需要更好地理解它。有人能帮助我掌握这个吗?
答案 0 :(得分:2)
这是一个经典的例子:
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
的任何内容现在都会被破坏。
一般来说, 很难通过查看代码来检测此问题,您必须分析数据 并告诉自己“global_int
正在被不同的线程访问,我最好用互斥锁来保护它”。如果你试图变得聪明并且担心线程将如何访问 以避免锁定的代价,那么除非是在琐碎的情况下,否则你可能会错。
答案 1 :(得分:1)
竞争条件是并发执行代码的结果,它在没有适当机制的情况下访问共享资源,以确保该共享资源的一致性。
如果线程调度程序的实现中存在导致用于执行上下文切换的代码访问共享资源而不提供适当的一致性保证的错误,则在上下文切换期间可能发生竞争条件。实现上下文切换的代码没有任何内容可以使它无法包含竞争条件。
答案 2 :(得分:0)
假设您使用的是具有调度程序的单处理器计算机,该调度程序基本上对可用处理器的资源执行时间分片(即,我们在非常简单的系统上)。然后假设您有一个关键的代码段,但是您没有使用互斥或其他同步原语来保护该临界区。
假设thread A
位于关键部分内。当thread A
的时间片结束时,调度程序会安排另一个thread B
并停止thread A
。 Thread B
然后进入临界区(因为没有防护),并修改临界区中共享内存中的值。当thread B's
时间片结束时,操作系统再次安排thread A
,从关键部分内部的点开始继续。现在唯一的问题是thread A
正在使用的值不是它们在上下文切换时停止的情况......它们完全不同,因为它们被thread B
修改了。因此,你有一个竞争条件。