2

我正在阅读有关信号量及其操作的文本。作者强调信号量的wait()post()操作应该原子执行,否则可能违反线程互斥。谁能给我解释一下他的意思?顺便说一句,我是多线程的新手

4

2 回答 2

2

上下文切换的操作,其中一个任务/进程被内核替换为另一个,是异步和不确定的。

让我们检查以下代码:

x++;

看起来很简单,哈?但是,如果 x 在不同的任务/进程之间共享,则此代码容易出现同步错误。

要理解这一点,您必须了解原子操作的概念。

原子操作是处理器可以在单个时钟上执行的指令。它通常涉及读取寄存器、写入寄存器等。

回到代码示例:当递增变量时,在幕后(汇编)实际发生的是 cpu 将变量的值读入寄存器。然后,它增加它。然后它将它保存回它从(内存)工具它的原始位置。

如您所见,像这样的简单操作涉及 3 个 cpu 步骤。上下文切换可以在这 3 个步骤之间发生。

让我们举一个需要增加同一个变量 x 的两个线程的例子。

让我们检查一个想象的(但可能的)场景的伪汇编代码

  1. 读取要注册的值(线程 1)
  2. 增加值(线程 1) CONTEXT SWITCH
  3. 读取要注册的值(线程 2)
  4. 增加值(线程 2)
  5. 保存值(线程 2) CONTEXT SWITCH
  6. 保存值(线程 1)

如果 x 是 3,现在看来它需要是 5,但它会是 4。

现在,让我们参考您的原始问题。信号量/互斥体实际上是一个变量。当一个进程想要接受它时,它会增加它。

于 2012-12-22T18:23:22.540 回答
0

是的,如果信号量上的wait()post()操作没有原子地执行,线程的相互执行可能会被违反。

例如,考虑一个具有值S = 1和进程的信号量,P1P2尝试wait()同时执行如下,

在 time T0T1process P1,分别P2找到 semaphore 的值,S = 1然后递减 semaphore 以获取锁并同时进入临界区,违反了线程的相互执行。

建议在获得锁之前 使用自旋锁wait()post() 自旋锁之间的原子性。

于 2012-12-22T18:48:51.400 回答