考虑这个功能:
void foo(int * p)
{
// something
}
编译器是否可以假设没有其他线程会修改p指向的值?或者它是否必须表现得好像可以随时修改这个值?
void bar(volatile int * p)
{
}
如果没有,volatile
关键字有帮助吗? GOTW #69指出编译器通常会忽略volatile
关键字。
修改: 显然,对“编译器假定”这一短语存在一些误解。让我澄清一下:
*p
的值放入寄存器,然后使用它直到p超出范围。此时,它应该在该内存地址写入*p
的值。 *p
时,编译器都应该从内存中获取它的值,因为有可能某个其他线程修改它。每次更改*p
时,编译器都应将其写入内存,以便其他线程可以读取它答案 0 :(得分:3)
编译器可以而且确实假设没有其他线程会修改p
指向的值,这意味着您必须确保您的代码不依赖于此,或者它具有适当的值同步机制,以避免竞争条件。换句话说,编译器做出假设,并且该假设可能是错误的。
volatile
关键字与此无关。
答案 1 :(得分:2)
规则是这样的:如果一个线程在另一个线程读取或写入同一位置的同时写入数据位置,则程序具有数据争用,并且程序的行为未定义。在行之间读取,编译器将假设没有其他线程正在写入您的数据。防止数据竞争是你的工作。并且,不,volatile
不会影响它。
答案 2 :(得分:1)
如果没有,volatile关键字有帮助吗?
编译器忽略它(即没有优化)而不是线程。
答案 3 :(得分:1)
每个线程都有自己的参数副本,表示该线程中发生的调用。 'p'的值只有在实际上它们都指向同一个东西时才会被共享。在另一个线程中分配给'p'不会影响该线程中的'p',因为它们甚至不是同一个变量。
'p'指向的是一个完全不同的故事。这只是一个记忆区域。如果其他线程可以访问它,那么他们可以访问它,他们可以随时写入它。保护像这样共享的东西的唯一方法是使用互斥锁。