如果我在互斥锁之间声明一个变量并返回它,我是否需要使用volatile关键字?

时间:2013-05-04 17:38:41

标签: c++

假设我有以下功能。

std::mutex mutex;

int getNumber()
{
    mutex.lock();
    int size = someVector.size();
    mutex.unlock();
    return size;
}

这是一个在声明大小时使用volatile关键字的地方吗?如果我不使用volatile,会返回值优化还是别的东西会破坏这段代码?可以从程序拥有的众多线程中更改someVector的大小,并假设只有一个线程(修饰符除外)调用getNumber()

3 个答案:

答案 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忙一点)以及在多个线程可能看同一个变量的系统中。它有时可以帮助多线程的东西,但它不是一个真正的线程,当然不是一个银弹