Language agnostic 与同步、发生在关系之前并获取发布语义

Language agnostic 与同步、发生在关系之前并获取发布语义,language-agnostic,synchronization,atomic,memory-barriers,Language Agnostic,Synchronization,Atomic,Memory Barriers,我需要帮助理解同步与关系。我读得越多,越是试图理解这个例子,我就越觉得自己什么都不懂。有时我觉得就在这里,我已经知道了,但在看了另一个例子后,我又困惑了。请帮我把它弄对 如果A是某个原子变量m的存储,具有释放语义,B是来自同一个变量m的加载,具有获取语义,并且B读取A存储的值,则操作A与操作B同步。 也有人说,如果 A在与B相同的线程上执行,并且A在程序顺序中位于B之前,或者 A与B同步,或 A发生在其他操作C之前,C发生在B之前 嗯。如果我们看看这个例子 thread0执行| thread

我需要帮助理解同步与关系。我读得越多,越是试图理解这个例子,我就越觉得自己什么都不懂。有时我觉得就在这里,我已经知道了,但在看了另一个例子后,我又困惑了。请帮我把它弄对

如果A是某个原子变量m的存储,具有释放语义,B是来自同一个变量m的加载,具有获取语义,并且B读取A存储的值,则操作A与操作B同步。 也有人说,如果

  • A在与B相同的线程上执行,并且A在程序顺序中位于B之前,或者
  • A与B同步,或
  • A发生在其他操作C之前,C发生在B之前
嗯。如果我们看看这个例子

thread0执行| thread1执行


存储x(释放)|加载x(获取)

此处存储到x是否与从x加载同步?如果我们在这里有与关系的同步,那么存储到x发生在从x加载之前,所以线程0中存储到x之前排序的所有内容都发生在线程1中从x加载之前。这意味着这里有强制命令。是这样吗?但在这种情况下,我不明白定义的“和B读取A存储的值”部分是什么意思?如果线程1比线程0快,它可能会读取旧值。那么这里的关系是什么,有什么关系吗?如果没有,我如何提供这种关系


提前谢谢。

我不能说我对这个术语很熟悉,但我认为这就是它的发展方向。我将使用.NET定义来定义术语:“如果其他处理器总是在任何后续操作的效果之前看到它的效果,则操作具有获取语义。如果其他处理器在操作本身的效果之前看到前面每个操作的效果,则操作具有释放语义。”

在本例中,存储和加载之间没有强制排序。任何一个都可以先执行。加载前执行存储操作时,A与B同步。发生这种情况时,存储(释放)之前的所有操作都保证在执行加载(获取)之后的操作之前执行

然而,加载操作可以在存储之前执行。在这种情况下,A与B不同步(因为条件“且B读取A存储的值”为非真),因此加载后的操作可能在存储之前的操作之前执行。命令含糊不清

release语义保证,对于x的特定值,我们将知道存储之前的操作将在我们能够在第二个线程中加载相同的存储值之前(以及在我们能够执行加载之后的操作之前)执行

假设count和flag初始化为零,并且两个线程并行运行:

thread0:
st          count, 1   (A)
st.release  flag, 1    (B)

thread1:
ld.acquire  flag       (C)
ld          count      (D)
我们知道A发生在B之前,C发生在D之前,因为它们的顺序是由释放和获取语义强制的。B和C的顺序未定义。只有当B与C同步时,我们才知道A发生在D之前(正如A发生在B之前,C发生在D之前)

在thread1中,如果标志为1,则计数始终为1。如果标志为0,则计数可以是0或1。我们可以测试该标志,以确定另一个线程是否已将该值设置为计数

如果没有acquire和release语义,加载和存储可以重新排序,并且标志和计数可以是0或1,彼此之间没有依赖关系

如果我们想确保B发生在C之前,我们可以使用信号量或其他一些等待和信号机制。在前面的示例中,我们可以通过忙于等待设置标志来强制执行命令

thread1:
ld.acquire  flag       (C)
repeat C while flag == 0
ld          count      (D)
这里有一篇很棒的文章