我正在阅读有关信号量及其操作的文本。作者强调,信号量的wait()
和post()
操作应该以原子方式执行,否则可能会违反线程的互斥。请问任何人,请向我解释他的意思?
答案 0 :(得分:2)
上下文切换的操作,其中任务/进程被内核替换为另一个任务/进程是异步和不确定的。
让我们检查以下代码:
x++;
看起来很简单,哈?
但是,如果x在不同的任务/进程之间共享,则此代码容易出现同步错误。
要理解这一点,你必须理解原子操作的概念。
原子操作是处理器可以在单个时钟上执行的指令。 它通常涉及读取寄存器,写入寄存器等等。
回到代码示例: 在递增变量时,幕后(汇编)实际发生的是 cpu将变量的值读入寄存器。 然后,它增加它。 然后它将它保存回原始位置(内存)。
正如您所看到的,这样的简单操作涉及3个cpu步骤。 上下文切换可以在这3个步骤之间进行。
让我们举两个需要增加相同变量x的线程的例子。
让我们检查虚构(但可能)场景的伪汇编代码
如果x为3,则现在看起来需要为5,但它将为4。
现在,让我们来看你原来的问题。 信号量/互斥量实际上是一个变量。 当一个过程想要接受它时,它会增加它。
答案 1 :(得分:0)
是的,如果信号量上的wait()
和post()
操作没有原子地执行,则可以违反线程的相互执行。
例如,考虑一个值为S = 1
且流程P1
和P2
的信号量尝试同时执行wait()
的信号量,
在时间T0
,T1
进程P1
,P2
分别找到信号量的值为S = 1
,然后递减信号量以获取锁定和同时进入临界区,违反了线程的相互执行。
在wait()
和post()
spin-locking之间使用原子性,直到获得锁定为止。