从OpenMP摘要pdf:“操作确保特定存储位置以原子方式更新”。这给我提出了一个问题,即“原子”是什么,而它只是一个锁定机制。因此,如果我没记错,“原子”意味着内置了一些硬件支持以防止其他任何内容更改值。那么制作“原子”的东西本质上只是实现一种锁机制还是更多呢?
答案 0 :(得分:1)
我认为围绕“原子性”与“隔离”可能存在一些混淆。它们是类似的概念,但它们之间存在细微差别。原子性意味着操作要么完全完成,要么根本不完成。隔离保证同时发生的操作会导致可能由它们串行执行的状态。
例如,如果操作是“将x加1,则将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文档中的含义。
答案 1 :(得分:0)
更新存储在内存中的值分为三个步骤。首先,从内存中获取值并将其带到CPU的一个寄存器中。然后,寄存器中的值以某种方式改变(例如递增)。最后,将新值写回内存,以便可以再次使用。
以原子方式执行此(或任何其他)操作只是意味着所有这三个步骤都会发生,或者没有一个步骤发生。
当您有另一个线程或进程也需要使用相同的内存值时,它才会变得有趣或重要。假设两者都想增加该值,该值最初为零。没有原子操作,第二个线程可能会从内存中读取原始值(0),即使第一个线程正在寄存器中递增它。实际上,两个线程都可以看到值0,将其增加到1,然后将其返回到内存。在此序列结束时,尽管已增加两次,但内存中的值将为1。
使用原子增量操作,无法发生该序列。一旦第一个线程进入原子序列,第二个线程就无法在第一个线程增加它并将其写回内存之前读取内存中的值。你总能得到正确的值(2)。
所以,为了回答你的问题,它几乎就像一个锁定机制 。特别是,它就像一个锁定机制存在于原始操作周围。原子操作本身经常用于实现其他锁定机制,例如互斥锁和信号量。