1

来自 OpenMP 摘要 pdf:“操作确保以原子方式更新特定存储位置”。这为我提出了一个问题,什么是“原子”,以及它是否只是一种锁定机制。因此,如果我没记错的话,“原子”意味着内置了一些硬件支持以防止其他任何东西改变值。那么做一些“原子”的东西本质上只是实现了一个锁定机制还是更多的东西?

4

2 回答 2

1

我认为围绕“原子性”与“隔离”可能存在一些混淆。它们是相似的概念,但它们之间存在细微差别。原子性意味着操作要么完全完成,要么根本不完成。隔离保证同时发生的操作会导致可能由它们串行执行引起的状态。

例如,如果操作是“将 1 加到 x,然后将 x 乘以 2”,并且 x 从 3 开始,则如果有任何失败,结果将为 3,如果没有,则结果为 8。即使加 1 后立即断电,重启时的结果也保证为 3。

现在考虑如果这个操作同时执行两次会发生什么。两者都可能失败,导​​致 x=3。一个可能会失败,x=8。两者都可以成功,x=18。如果我们保证隔离,这些是唯一的结果。但是,如果我们只给定原子性,而不是隔离,可能会发生第四个结果,其中各个部分交错为“加 1,加 1,乘以 2,乘以 2”,导致 x=20!

如果只保证隔离,但不保证原子性,则最终可能会得到 x=3、4、5、8、10 或 18。

尽管如此,这是一个常见的误解,当人们说“原子性”时,他们通常是指两者。这是我对 OpenMP 文档中它们的含义的怀疑。

于 2012-08-01T00:04:59.157 回答
0

更新存储在内存中的值是一个三步过程。首先,从内存中取出值并将其带到 CPU 的一个寄存器中。然后,寄存器中的值以某种方式改变(比如递增)。最后,将新值写回内存,以便再次使用。

以原子方式执行此(或任何其他)操作仅意味着所有这三个步骤都会发生,或者它们都不会发生。

只有当您有另一个线程或进程也需要使用相同的内存值时,它才会变得有趣或重要。假设两者都想增加最初为零的值。如果没有原子操作,第二个线程可能会从内存中读取原始值 (0),即使第一个线程在寄存器中递增它也是如此。实际上,两个线程都可以看到值 0,将其递增到 1,然后将其返回到内存。在此序列结束时,尽管已增加两次,但内存中的值仍为 1。

使用原子增量操作,该序列不可能发生。一旦第一个线程进入原子序列,在第一个线程递增并将其写回内存之前,第二个线程无法读取内存中的值。您将始终获得正确的值 (2)。

因此,要回答您的问题,它几乎就像一个锁定机制。特别是,它就像一个锁定机制存在于任何原始操作周围。原子操作本身经常用于其他锁定机制的实现,例如互斥锁和信号量。

于 2012-07-18T11:09:29.447 回答