我们何时应该使用关键字' volatile'?

时间:2014-06-27 23:35:20

标签: c volatile

我知道“易变”的一些基础知识。但我仍然要说清楚:))

如果内存中的某些变量将被硬件修改,我知道我们需要使用' volatile'保护它。但是,我的问题是:

  1. 如果变量将由同一文件中的另一个函数修改;
  2. 如果变量将被同一项目中的另一个函数修改(在不同的文件中,代码可能属于不同线程的同一个线程)。
  3. 您是否需要使用' volatile'?

    谢谢,

3 个答案:

答案 0 :(得分:3)

在C中,volatile关键字指示编译器不做任何假设,也不做“切角”,只做所有的工作。这意味着变量将始终从存储器中读取和写入,而不是保存在寄存器中。编译器还将忽略本地上下文可能对变量所暗示的所有内容,并避免进行某些优化。

哪个文件或哪个函数真的无关紧要,只要变量值有可能从程序中的多个点(或者甚至是另一个进程或其他硬件机制)中改变,它应该是标记为易失性,以便从其实际位置检索正确的值,而不是使用假定值或来自寄存器的缓存副本或完全优化掉。

另请注意volatile变量上的操作不是原子的。你应该在多线程场景中使用原子。

简而言之 - volatile主要用于低级硬件操作,通常当代码之外的其他内容可能会更改变量时,应该在应用程序开发中使用它(如果有的话)。它主要用于微控制器/硬件驱动程序。

答案 1 :(得分:2)

使用volatile告诉编译器不要尝试缓存(希望优化访问)它声明的变量。这包括硬件修改内存和对同一内存的多线程访问的实例。

虽然在多线程的情况下,我建议您考虑使用互斥锁(或其他可用的同步工具)

答案 2 :(得分:0)

volatile并未广泛使用,但有一些实际的例子。我会告诉你一个。

首先,看看这个。

#include <stdio.h>
#include <threads.h> // C11 threading library

int i = 0;

int noticer_thread(void *arg)
{
    while (getchar() == 'a') // suppose something happened!
        i = 1;
    return 0;
}

int main()
{
    thrd_t thrd;
    int res;

    thread_create(&thrd, noticer_thread, NULL);

    while (i != 1) { /* wait... */ }
    printf("something happened!\n");

    thrd_join(thrd, &res);
}

(我刚试过C11线程库 - 只练习^ o ^)

你能注意到什么问题吗?编译器知道i将被另一个线程更改,因此while main循环可以优化,如下所示 -

register int EAX = i;
while (EAX != 1) { ...

此外,i应为volatile

volatile int i = 0;

那么,为什么它是实用的例子呢?事实上,我在我的os开发中遇到了这种错误。假设noticer_thread是中断处理程序,main是内核线程。 noticer_thread设置了一个标志,通知main中断,但mainvolatile之后无法知道!