3

如果我有以下伪代码:

sharedVariable = somevalue;
CreateThread(threadWhichUsesSharedVariable);

理论上,多核 CPU 是否可以在 threadWhichUsesSharedVariable() 中执行代码,该代码在父线程写入之前读取 sharedVariable 的值?为了在理论上完全避免竞争条件的可能性,代码应该看起来像这样:

sharedVariableMutex.lock();
sharedVariable = somevalue;
sharedVariableMutex.unlock();
CreateThread(threadWhichUsesSharedVariable);

基本上我想知道线程的产生是否在那时显式地线性化了 CPU,并保证这样做。

我知道线程创建的开销可能需要足够的时间,这在实践中并不重要,但我的完美主义者害怕理论上的竞争条件。在极端条件下,一些线程或内核可能严重滞后,而其他线程或内核运行得又快又高效,我可以想象,除非有锁,否则执行顺序(或内存访问)可能会被逆转。

4

2 回答 2

2

我会说您的伪代码在任何正常运行的多处理器系统上都是安全的。C++ 编译器无法生成对 CreateThread()beforesharedVariable收到正确值的调用,除非它可以向自己证明这样做是安全的。您可以保证您的单线程代码等效于完全非重新排序的线性执行路径。任何在变量赋值之前“时间扭曲”线程创建的系统都会被严重破坏。

在这种情况下,我认为声明sharedVariable为 volatile 没有任何用处。

于 2010-02-11T16:52:35.083 回答
1

鉴于您的示例,如果您使用的是 Java,那么答案将是“否”。在 Java 中,线程不可能在赋值操作完成之前生成并读取您的值。 在其他一些语言中,这可能是另一回事。

“在多个线程之间共享的变量(例如对象的实例变量)具有由 Java 语言规范保证的原子赋值,用于除 long 和 double 之外的所有数据类型......如果一个方法仅由单个变量访问或赋值组成,则没有需要使其同步以确保线程安全,并且有充分的理由不这样做以提高性能。” 参考

如果您的doubleorlong被声明volatile,那么您也可以保证分配是原子操作。

更新: 您的示例将在 C++ 中运行,就像在 Java 中一样。从理论上讲,即使是乱序执行,线程生成也不会在分配之前开始或完成。

请注意,您的示例非常具体,在任何其他情况下,建议您确保正确保护共享资源。新的 C++ 标准出现了很多原子的东西,所以你可以将你的变量声明为原子的,并且赋值操作对所有线程都是可见的,而无需锁定。CAS(比较和设置)是您的下一个最佳选择。

于 2010-02-11T03:26:44.893 回答