为相当简单的操作实现线程安全的最佳方法是什么?
考虑一对函数:
void setVal(int val)
{
this->_val = val;
}
int getVal() {
return this->_val;
}
由于原始类型的赋值不能保证是原子的,我是否应该按照以下方式修改程序中的每个getter和setter以保证线程安全?
void setVal(int val)
{
this->_mutex.lock();
this->_val = val;
this->_mutex.unlock();
}
int getVal() {
this->_mutex.lock();
int result = this->_val;
this->_mutex.unlock();
return result;
}
答案 0 :(得分:6)
您是否在多个线程中使用_val
?如果没有,那么不,你不需要同步访问它。
如果从多个线程使用它,那么是的,您需要使用互斥锁或使用原子类型(如C ++ 0x中的std::atomic<T>
)来同步访问,尽管其他线程库具有非标准原子类型)。
答案 1 :(得分:1)
互斥体非常昂贵,因为它们可以跨进程共享。如果您限制访问的状态仅限于当前进程中的线程,那么请选择不那么重的东西,例如Critical Section或Semaphore。
答案 2 :(得分:1)
在32位x86平台上,在4字节边界上对齐的32位值的读取和写入是原子的。在64位平台上,您还可以依赖64位加载和8字节对齐值的存储也是原子的。 SPARC和POWER CPU也可以这样工作。
C ++没有做出这样的保证,但实际上没有编译器会搞乱它,因为每个非平凡的多线程程序都依赖于这种行为。
答案 3 :(得分:-3)
int getVal() {
this->_mutex.lock();
int result = this->_val;
this->_mutex.unlock();
return result;
}
你到底想要完成什么?当然,在保存到this->_val
之前,你已经停止了result
的更改,但是在结果返回之前它仍然可能会发生变化,或者在返回和分配给你指定的任何内容之间 - 或者微秒后。无论你做什么,你只需要获得移动目标的快照。处理它。
void setVal(int val)
{
this->_mutex.lock();
this->_val = val;
this->_mutex.unlock();
}
同样,这对你有什么用?如果您同时从不同的线程中调用setVal(-5)
和setVal(17)
,那么完成后应该有什么值?你已经遇到了一些麻烦,以确保第一个开始也是第一个完成,但是如何帮助设置“正确”值?