boost :: atomic有函数存储和加载。但是,有一个函数可以返回当前值并同时设置值,这意味着这两个操作都是原子的。
以下代码是问题
void Initialize()
{
///if some other thread is initializing, skip this step
if (m_initializing.load(boost::memory_order_relaxed))
return S_FALSE;
m_initializing.store(true, boost::memory_order_relaxed);
return S_OK;
}
如果两个线程同时调用此初始化函数。线程A和B调用load并返回false,它们将同时调用store。所以我想要一个原子功能。如果A发现m_initializing为false,并且同时设置为true。所以线程B知道某个线程正在处理它。
答案 0 :(得分:0)
你的方法比初看起来更棘手。
根据评论部分的建议,
替换exchange()
的读 - 修改 - 写(RMW)load()
可以解决访问同一区域的多个线程的问题,
但是,在初始化尚未完成时,您期望另一个线程会做什么?毕竟,您的标志表示初始化例程正在运行,而不是它已经完成。
此外,使用memory_order_relaxed
并不能保证初始化数据与调用Initialize()
的其他线程正确同步。
至少你必须使用获取/释放语义,但由于标志(exchange()
)现在设置在开头,它还没有'释放'任何东西。
使用mutex
要容易得多,它负责线程序列化和线程间同步。此外,使用指示状态initialized
的标志。
bool m_initialized{false};
boost::mutex m_mut;
void Initialize()
{
boost::lock_guard<boost::mutex> lck{m_mut};
if (m_initialized)
return; // already initialized
// ... initializing part
m_initialized = true;
return;
}
由于mutex
同步了受保护区域中的所有内容,m_initialized
现在可以成为常规bool
(除非它也用于其他地方)。
我建议用boost
替换mutex
并发原语(atomic
,std
)。它们已被boost
中的标准采用,并且自C ++ 11起可用