假设我有以下功能。
std::mutex mutex;
int getNumber()
{
mutex.lock();
int size = someVector.size();
mutex.unlock();
return size;
}
这是一个在声明大小时使用volatile
关键字的地方吗?如果我不使用volatile,会返回值优化还是别的东西会破坏这段代码?可以从程序拥有的众多线程中更改someVector
的大小,并假设只有一个线程(修饰符除外)调用getNumber()
。
答案 0 :(得分:8)
没有。但请注意,size
可能无法反映互斥体释放后的实际大小。
编辑:如果你需要做一些依赖于size
正确的工作,你需要使用互斥锁包装整个任务。
答案 1 :(得分:5)
你还没有提到mutex
变量的类型是什么,但是假设它是std::mutex
(或类似的东西意味着保证互斥),编译器就无法执行很多优化因此,您无需担心返回值优化或其他一些优化,从而允许size()
查询在互斥块之外执行。
但是,只要释放互斥锁,另一个等待线程就可以自由访问该向量并可能使其变异,从而改变大小。现在,您的函数返回的数字已过时。正如Mats Petersson在他的answer中提到的那样,如果这是一个问题,则需要由getNumber()
的调用者获取互斥锁,并保持直到调用者使用结果完成。这将确保矢量的大小在操作期间不会改变。
对于涉及异常,多个返回语句等更复杂的函数,显式调用mutex::lock
后跟mutex::unlock
很快变得不可行。更容易的替代方法是使用std::lock_guard
来获取互斥锁。
int getNumber()
{
std::lock_guard<std::mutex> l(mutex); // lock is acquired
int size = someVector.size();
return size;
} // lock is released automatically when l goes out of scope
答案 2 :(得分:1)
Volatile是一个关键字,用于告诉编译器实际上写入或读取变量而不应用任何优化。这是一个例子
int example_function() {
int a;
volatile int b;
a = 1; // this is ignored because nothing reads it before it is assigned again
a = 2; // same here
a = 3; // this is the last one, so a write takes place
b = 1; // b gets written here, because b is volatile
b = 2; // and again
b = 3; // and again
return a + b;
}
这有什么用途?我已经在延迟函数中看到它(通过使计数到一个数字来保持CPU忙一点)以及在多个线程可能看同一个变量的系统中。它有时可以帮助多线程的东西,但它不是一个真正的线程,当然不是一个银弹