【问题标题】:C++ optimization leading to thread lockingC++ 优化导致线程锁定
【发布时间】:2017-02-23 08:50:35
【问题描述】:

我制作了一个具有以下特点的程序:

这是在 ClassA 中工作的

变量:

int8_t* p1; // this is only modified on thread1
volatile int8_t* p2;

thread1(被锁定)

while(p1 + 64 > p2);

thread2(修改 p2)

while(true)  {  
    //reading file
    p2 += 10;
    //reading file
    p2 += 10;
    //reading file
    p2 += 10;
}

Thread1 在某个时候被锁定。但是,将 thread1 更改为下面的代码会使 thread1 永远不会被锁定。

while(p1 + 64 > p2) {
    printf("%d\n", p1);
}

我用-Ofast 编译了这段代码。我想问题是优化。如何在不修改编译器标志的情况下解决此问题?

【问题讨论】:

  • 不要使用 volatile 进行线程同步。

标签: c++ multithreading compiler-optimization


【解决方案1】:

p1p2 使用互斥体或使用适当的原子类型。在 C++ 中,volatile 没有定义的多线程语义。在另一个线程可能正在访问它时修改常规变量(如p2)会产生不可预测的结果。不要这样做。

【讨论】:

  • 我在代码上犯了一个错误。 volatile 变量是 p2 而不是 p1
  • 没什么区别。不要使用volatile。使用原子类型或互斥体。
【解决方案2】:

p2 是在你第一个线程之外修改的变量,因此应该声明为 volatile。

即便如此,还是使用原子或互斥体。 volatile 不会保护乱序读取和写入。在 linux 上,互斥量在没有争用的情况下非常便宜。

【讨论】:

  • volatile 与跨线程的数据同步无关。
  • Volatile 告诉编译器内存地址 van 在当前线程之外被修改,无论是硬件、操作系统还是其他线程。因此,尽管不建议使用它,但在这种情况下可能会有所帮助。
  • 当然,volatile 在这种情况下可能会有所帮助:它可能会暂时隐藏真正的问题,这当然意味着真正的问题会在您为最重要的客户演示代码时出现; “嗯,它曾经有效”不会是可接受的回答。
  • volatile 最大的问题是乱序读写。当然,您可以设置内存屏障,而只需使用适当的 api 来为您处理这个问题。所以我同意 100% 不稳定是一个坏主意,除非你真的知道自己在做什么以及在哪个平台上。
猜你喜欢
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 2017-07-02
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 2013-07-13
相关资源
最近更新 更多