Multithreading 几个线程在缓冲区中写入相同的数据:是否有一致的参数表明这是危险的?

Multithreading 几个线程在缓冲区中写入相同的数据:是否有一致的参数表明这是危险的?,multithreading,synchronization,race-condition,Multithreading,Synchronization,Race Condition,想象一种情况,在这种情况下,多个线程可以在某个缓冲区上写入(对其大小没有限制),并且所有这些限制都适用: 在所有线程开始之前,缓冲区被初始化为零 线程可以在缓冲区上写入,也可以不写入 如果一个线程在缓冲区上写入,它会写入一个特定的字节字符串(我们称之为V,其中V不仅由零组成,而且对所有线程都是相同的) 没有线程从缓冲区读取数据 一个线程在缓冲区上写的事实,以及它在缓冲区上写的内容,并不取决于其他线程是否在缓冲区上写过 如果线程开始在缓冲区上写入,那么它将完全写入 线程在缓冲区上写入数据,而不遵循

想象一种情况,在这种情况下,多个线程可以在某个缓冲区上写入(对其大小没有限制),并且所有这些限制都适用:

  • 在所有线程开始之前,缓冲区被初始化为零
  • 线程可以在缓冲区上写入,也可以不写入
  • 如果一个线程在缓冲区上写入,它会写入一个特定的字节字符串(我们称之为
    V
    ,其中
    V
    不仅由零组成,而且对所有线程都是相同的)
  • 没有线程从缓冲区读取数据
  • 一个线程在缓冲区上写的事实,以及它在缓冲区上写的内容,并不取决于其他线程是否在缓冲区上写过
  • 如果线程开始在缓冲区上写入,那么它将完全写入
  • 线程在缓冲区上写入数据,而不遵循字节的精确顺序
  • 问题是:在所有线程都停止之后(如果它们已经开始在缓冲区上完成了写操作,那么这种情况才会发生),在任何真实世界或至少合理的体系结构下,我是否可以保证:

  • 要么缓冲区包含所有零
  • 或者缓冲区正好包含
    V

  • 如果没有,是否有一致的参数说明可能会写入另一个字节字符串,称之为
    V'
    ?如果是,那么
    V
    V'
    之间有什么区别?为什么?

    第6项似乎是关键,它基本上说明了对缓冲区的写入是原子的,不可中断的。因此,内容将为0或一致的
    v

    当然,这不是线程的正常情况,除非您使用互斥锁之类的东西。

    是的,这是有保证的(如果所有线程都将相同的值写入相同的位置)。字节的存储是原子的。这意味着系统不能“编造”任何值。缓冲区中每个字节的唯一可能值是零(因为它是预初始化的)或所有线程写入的值

    现在的问题是:零滑能以某种方式实现吗?
    字节[]
    中的某个位置是否会以某种方式看起来从未被写入过?答:没有。不清楚是哪封信通过的,但它们都是一样的。如果至少有一个线程写入缓冲区,它将正好包含
    V
    。(如果没有人写它,它将是全零。这很简单。所以我假设至少有一个线程写入了缓冲区)


    当然,您的阅读线程必须等待写入程序终止,以强制设置内存障碍。屏障保证读卡器可以看到之前的所有写入操作。

    问题不在于“缓冲区是否包含0s或V”:它确实包含您所写的内容-更有趣的问题是:“如果我读取缓冲区,是否保证读取0s或V”。后者的答案取决于你现实世界的内存模型,或者至少是合理的架构,而这又取决于你所使用的语言/执行框架/cpu…V对所有线程都是一样的吗?@assylias:请给出一个详细的答案好吗?我想阅读你的观点,这与已经回答的人的观点不同-前提是你对问题的解释是相同的。@gd1我对答案没有足够的把握来发布一个-但我的感觉是,如果你的缓冲区足够大(并且在缓存线之间分割),它对主存的更新不会是原子性的,如果不使用适当的内存屏障强制执行可见性,则读取线程可能会从主存读取部分更新。现在,这个部分更新将被观察到的窗口在大多数架构上可能很短。如果你用C++编写这个编译器,编译器会把它全部搞乱,如果不是今天,那么在将来的版本中。允许它以任何方式重写代码,只要结果与您编写的代码相同,并且在这样做的过程中,允许它假设您没有比赛——因此,既然您有比赛,所有赌注都没有了。例如,它可以使用先将V写入缓冲区但向上移动一个字节,然后向下移动缓冲区内容的代码重写线程回调。当两个线程同时执行此操作时,结果可能不是V或0。