在多线程处理时重新审视 C 中的“易失性”

问题描述 投票:0回答:1

我在这里阅读了许多有关此主题的问题,但仍然觉得我读到的许多答案都没有抓住要点。

问题:纯C中线程之间共享的变量是否应该标记为

volatile

免责声明:我非常理解

volatile
并不意味着原子。也就是说,仅仅因为我的变量被标记为
volatile
并不意味着我不需要担心竞争条件。

要点:如果我有一个变量

A
,它通过使用互斥锁而成为原子变量,那么
A
不应该仍然标记为
volatile
以防止编译器优化对
A
的读取吗?

考虑以下示例:

mutex_t m;
static int flag = 0;

// Thread 1
void writer(void) {
  lock(m)
  flag = 1;
  unlock(m);
}

// Thread 2
void reader(void) {
  int read = 0;
  while (1) {
    lock(m);
    read = flag;
    unlock(m);

    if (read) exit(0);
  }
}

鉴于函数

writer
reader
在不同的线程中执行,编译器是否可以优化
flag
函数内对
reader
的重复读取?

我觉得这里应该制作旗帜

volatile

最终免责声明:我知道可能存在一个很好的原子/线程安全类型,可以用于像本例中的

flag
这样的小整数值。然而,我更多地问这个问题是针对两个线程之间共享的数据是一个大结构的情况。

c multithreading
1个回答
0
投票

纯C中线程之间共享的变量是否应该被标记为

volatile

不,除非它们实际上是

volatile
,这意味着此类变量的值可能会在程序的控制之外发生变化。

不应该仍将

A
标记为
volatile
以防止编译器优化对
A
的读取吗?

再次强调,只有当

A
的值可以在程序控制范围之外更改时,或者
A
的读取有副作用时,比如它连接到对读取做出反应的硬件时。

我觉得这里应该制作旗帜

volatile

不应该。您已经使用互斥体保护了读取和写入,因此一切都很好,并且使其

volatile
可能会对程序的性能产生负面影响,因为它会强制编译器在可能不需要时实际从内存中读取
flag
到.

© www.soinside.com 2019 - 2024. All rights reserved.