Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Atomic 提高原子负荷,同时储存_Atomic - Fatal编程技术网

Atomic 提高原子负荷,同时储存

Atomic 提高原子负荷,同时储存,atomic,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(t

原子具有存储和加载功能。但是,有一个函数可以返回当前值并同时设置值,这意味着这两个操作是原子操作

下面的代码就是问题所在

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_initialization为false,则同时将其设置为true。因此线程B知道某个线程正在处理它。

您的方法比乍一看要复杂得多

正如评论部分所建议的, 读-修改-写(RMW)
exchange()
替换
load()
可以解决多个线程访问同一区域的问题, 但是,当初始化尚未完成时,您希望另一个线程做什么?毕竟,您的标志指示初始化例程正在运行,而不是它已经完成。 此外,使用
memory\u order\u relaxed
不能保证初始化数据与调用
Initialize()
的其他线程正确同步。 至少您必须使用acquire/release语义,但是由于标志(带有
exchange()
)现在是在开始时设置的,所以它还没有“释放”任何内容

使用
互斥体
要容易得多,它同时负责线程序列化和线程间同步。此外,使用一个标志指示状态
已初始化

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;
}
boolmu初始化{false};
boost::互斥m_mut;
void Initialize()
{
boost::lock_-guard lck{m_-mut};
如果(m_已初始化)
return;//已初始化
//…正在初始化部分
m_initialized=true;
返回;
}
由于
mutex
同步受保护区域中的所有内容,
m_initialized
现在可以是常规的
bool
(除非它也在其他地方使用)


我建议将
boost
并发原语(
mutex
atomic
)替换为
std
。它们已被标准从
boost
中采用,并且在C++11

中“同时加载和存储”被称为exchangeThanks后可用。我发现我想知道,若初始化步骤需要很长时间,那个么其他线程就会被阻塞。在互斥锁的保护下调用函数是不安全的,这可能会导致意外死锁。请您详细解释一下内存\u顺序\u松弛、获取/释放语义。我真的无法理解有关内存顺序的文档。@ernst初始化可能需要一些时间,但通常其他线程在初始化完成之前无法执行任何操作;虽然这很难说,因为这一部分的上下文缺失了。只要不递归调用
Initialize()
函数,如果使用此处所示的互斥锁,就不可能出现死锁。@ernst关于内存顺序的解释几乎需要一整章。下面是一个相关的@ernst顺便说一句,是什么让您认为互斥锁可能会导致意外死锁?死锁总是编程错误的结果,它不会无缘无故地发生。