use*_*625 8 c embedded multithreading
我读到了volatile内存映射硬件寄存器,ISR和多线程程序中C 关键字的用法.
1)注册
uint8_t volatile * pReg;
while (*pReg == 0) { // do sth } // pReg point to status register
Run Code Online (Sandbox Code Playgroud)
2)ISR
int volatile flag = 0;
int main()
{
while(!flag) { // do sth }
}
interrupt void rx_isr(void)
{
//change flag
}
Run Code Online (Sandbox Code Playgroud)
3)多线程
int volatile var = 0;
int task1()
{
while (var == 0) { // do sth }
}
int task2()
{
var++;
}
Run Code Online (Sandbox Code Playgroud)
我可以看出为什么编译器可以错误地优化while以防万一1)如果volatile不存在,'因为变量是由硬件进行的,编译器可能看不到代码所做的变量的任何变化.
但对于案例2)和3),为什么需要挥发性?在这两种情况下,变量都声明为全局变量,编译器可以看到它在多个地方使用.那么为什么编译器会优化while循环,如果变量不是volatile?
是因为编译器副设计不知道"异步调用"(在ISR情况下)或多线程?但这不可能,对吧?
此外,案例3)看起来像没有volatile关键字的多线程中的常见程序.假设我在全局变量中添加一些锁定(无volatile关键字):
int var = 0;
int task1()
{
lock(); // some mutex
while (var == 0) { do sth }
release()
}
int task2()
{
lock();
var++;
release();
}
Run Code Online (Sandbox Code Playgroud)
对我来说看起来很正常.那么我volatile在多线程中真的需要吗?为什么我从未见过将volatile限定符添加到变量中以避免以前在多线程程序中进行优化?
使用volatile关键字的要点是防止编译器生成使用CPU寄存器作为表示变量的更快方式的代码.这会强制编译代码在每次访问变量时访问RAM中的确切内存位置,以获取可能已由另一个实体更改的最新值.通过添加,volatile我们确保我们的代码知道任何其他人(如硬件或ISR)对变量所做的任何更改,并且不会发生一致性问题.
如果没有volatile关键字,编译器会尝试通过将RAM中的变量内容读入CPU寄存器一次并在循环或函数中使用该缓存值来生成更快的代码.访问RAM可能比访问CPU寄存器慢几十倍.
我已经有了第1项和第2项的经验,但我认为你不需要volatile在多线程环境中定义变量.添加锁定/解锁机制是解决同步问题所必需的,与所涉及的内容无关volatile.