C中非易失性变量的限制

时间:2013-05-28 16:26:17

标签: c compiler-construction concurrency volatile

我想了解编译器对C中的非易失性变量有什么限制。

我不确定它的真实与否,但我被告知如果您有以下代码:

int x;
...
void update_x() {
  lock();
  x = x*5+3;
  unlock();
} 

你必须获得锁读取x,因为即使编译器不太可能这样做,在技术上合法的是将x * 5等中间计算存储到x中,因此读取可能会读取中间值。所以我的第一个问题是它是否确实如此?如果没有,为什么不呢?

如果是,我有一个后续问题,是否有什么阻止编译器在获取锁之前或之后使用x作为临时存储? (假设编译器可以证明执行程序的单个线程不会注意到它)。

如果没有,这是否意味着即使所有访问都受到锁保护,任何具有非易失性共享变量的程序在技术上都是未定义的?

谢谢, 伊利亚安德

1 个答案:

答案 0 :(得分:1)

在C11之前,答案是否定,因为规范没有定义任何关于多个线程做什么的事情,所以任何使用多个线程的程序,其中一个线程写入一个对象而另一个线程读取它是未定义的行为。

对于C11,实际上有一个内存模型可以讨论多个线程和数据争用,所以答案是肯定的,只要锁定/解锁例程执行某些同步操作(涉及执行同步或操作的库函数)特殊_Atomic个对象)。

由于C11规范试图编写现有实现的行为(大多数情况下),很可能是任何代码执行它所需要的(即,使用实现提供的库进行锁定,或实现提供的原子扩展)操作)即使在C11之前的实现上也能正常工作。

C11规范的第5.2.1.4节涵盖了这一点。