同时提升原子载荷并存储

时间:2017-01-22 15:43:58

标签: atomic

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知道某个线程正在处理它。

1 个答案:

答案 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并发原语(atomicstd)。它们已被boost中的标准采用,并且自C ++ 11起可用