我知道“易变”的一些基础知识。但我仍然要说清楚:))
如果内存中的某些变量将被硬件修改,我知道我们需要使用' volatile'保护它。但是,我的问题是:
您是否需要使用' volatile'?
谢谢,
答案 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
中断,但main
在volatile
之后无法知道!