6

假设我有以下功能。

std::mutex mutex;

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

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

4

3 回答 3

8

不会。但请注意,size释放互斥锁后,可能无法反映实际大小。

编辑:如果您需要做一些依赖于size正确性的工作,您将需要用互斥锁包装整个任务。

于 2013-05-04T17:44:26.807 回答
5

你没有提到mutex变量的类型是什么,但假设它是一个std::mutex(或类似的东西,以保证互斥),编译器被阻止执行很多优化。因此,您无需担心返回值优化或其他允许size()查询在互斥块之外执行的优化。

但是,一旦互斥锁被释放,另一个等待线程就可以自由访问该向量并可能对其进行变异,从而改变大小。现在,您的函数返回的数字已过时。正如 Mats Petersson 在他的回答中提到的那样,如果这是一个问题,那么互斥锁需要由 的调用者获取getNumber(),并一直保持到调用者使用结果完成为止。这将确保向量的大小在操作期间不会改变。


对于涉及异常、多个返回语句等的更复杂的函数,显式调用mutex::lock后跟快速调用变得不可行。一个更简单的替代方法是使用获取互斥锁。mutex::unlockstd::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
于 2013-05-04T18:03:16.647 回答
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 忙碌一段时间)以及多个线程可能查看同一个变量的系统中看到它。它有时可以在多线程的事情上有所帮助,但它并不是真正的线程事情,当然也不是灵丹妙药

于 2013-05-04T18:04:06.093 回答