【问题标题】:C volatile memory modelC 易失性存储器模型
【发布时间】:2016-12-03 09:45:09
【问题描述】:

volatile 关键字是否强制跨线程可见性?例如:

volatile int bar;
mutex mut;

void foo()
{
    bar = 4;

    // (*) Possible other thread changes to `bar`. No instructions here,
    // just time that passes.

    lock(&mut);

    // (1) If 'bar' had _not_ been declared 'volatile', would the compiler
    // be allowed to assume 'bar' is '4' here?
    //
    // (2) If 'bar' _is_ declared 'volatile', the compiler is 
    // forced to add the necessary instructions such that changes to
    // 'bar' that may have occurred during (*) are visible here.

    unlock(&mut)
}

不询问原子性或顺序(我假设lock(mutex) 的任何合理实现都会在适合架构的情况下添加适当的内存和编译器围栏)- 只是可见性问题。

【问题讨论】:

  • 什么叫“可见性”?如果您的意思是“所有线程都可以读取或写入变量”,编译器会告诉您。如果您的意思是“线程将看到分配的最后一个值”,那么问题确实与原子性或排序有关。请澄清。
  • @YvesDaoust 我的意思是“线程将看到分配的最后一个值”,但是,假设编译器/内存栅栏插入在 lock/unlock 周围,不要认为原子性或排序会出现在这里发挥作用。
  • 抱歉,这正是关于原子性或排序。在分配和锁定之间可能发生任何事情,无论是否易失。作业可能应该在关键部分内。
  • 你错了。主题是原子性和排序。可见性与范围有关,在这里完全不相关。
  • @user7226419:最后一次,你的词汇不合适。

标签: c multithreading volatile


【解决方案1】:

即使您不将bar 标记为易失性,编译器也无法确定该值同时未被修改,因为它是一个全局 值。

所以它必须再次读取它(互斥函数被调用,它可以是任何访问bar 并更改它的函数),无论是否易失。

local 值会有所不同,例如,绑定在硬件寄存器上,该寄存器可能会独立于程序执行而改变,其中需要 volatile 关键字。

【讨论】:

  • "即使你没有将 bar 标记为 volatile,编译器也无法确定该值是否同时没有被修改,因为它是一个全局值。"我不认为这是真的吗? volatile 解决了信号处理程序(除其他外)的服务需求,它肯定会对全局数据进行操作。
【解决方案2】:

(1) 如果“bar”没有被声明为“volatile”,编译器会 可以在这里假设“bar”是“4”吗?

volatile 的属性非常容易理解:每次都从内存位置读取它,而无需优化任何相关的东西。无论是否有多个线程,一个 volatile 限定变量仍然具有相同的属性。

这是否意味着volatile 强制跨线程“可见性”?

这可能是其属性的副作用。但这在多线程程序中不应该是必需的。使用适当的同步原语(例如互斥锁或原子变量),编译器必须跨不同线程强制对象中的可见性或最后存储的值。在 C11 和 POSIX 线程中都是这种情况。支持多线程程序的编译器应该能够生成代码正确的代码来强制执行此操作,而无需 volatile。所以,答案是否定的;您不需要在多线程程序中使用volatile 来强制更改对象(变量)。

【讨论】:

  • 对不起,是指指定 C99。
  • C99 没有线程。因此,该标准没有涵盖与多线程程序相关的任何内容。所以我们留下了实现特定的行为/文档。答案的一般要点仍然成立:如果编译器声称支持多线程,它不应该需要volatile。我已经使用(仍在使用)使用 GCC 的 POSIX 线程,并且从不需要 volatile
  • 编译器标志D_REENTRANT 是编译器理解它是一个多线程程序(并启用必要的线程安全等)所必需的。但那是很久以前的事了。它不再需要了。 GCC/Pthreads相关信息可以搜索comp.programming.threads
  • C99 可能没有线程作为语言结构(我认为这些东西不应该成为语言的一部分),但很多东西都是多线程的
  • 我发现这种时候语言会成为障碍。为支持的平台手动滚动组件可能更容易。至少这可以猜到哈!
猜你喜欢
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 2015-11-07
  • 1970-01-01
  • 2017-06-24
  • 2015-07-26
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多