3

我在 linux 上有一个带有两个线程的 c++ 程序 线程 A 将一些数据写入 std::map 没有其他数据将写入此映射然后线程 A 创建线程 B 线程 B 从映射中读取数据

那么在这种情况下我需要使用 Mutex 吗?

如果不是,那么该保证在哪里指定。

4

3 回答 3

5

不会。线程创建是一个同步点,因此在创建第二个线程之前第一个线程产生的所有效果将在创建第二个线程时“已经发生”(以一种可以在标准)。

更准确地说,在一个线程创建并随后加入另一个线程的上下文中......

  • 线程创建之前的所有事情都发生在线程函数内部的任何事情之前,并且
  • 线程函数内的所有事情都发生在线程加入之后的任何事情之前
于 2013-10-16T08:42:38.203 回答
2

不,只有当您想同时从两个或多个线程读取/写入内存时才需要互斥锁。因为,当你有多个线程时,你的 std::map 是不可变的,你不需要任何同步。您永远不需要不可变数据上的互斥锁。即使在您的情况下,线程 B 将写入 std::map,仍然只有一个线程会一次在此内存上读/写,并且您不需要同步一个线程。

于 2013-10-16T08:41:09.340 回答
1

事实上,只要有可能,主导模式应该是:

(可变)数据随任务移动

因此,数据归使用它的线程所有。现在,它不需要“物理”迁移,但使用移动语义可以让画面更清晰:

#include <map>
#include <string>

using namespace std;

using Map = map<string, int>;

Map worker(Map&& data)
{
    for (auto& el : data)
        el.second *= -1;

    return std::move(data);
}

#include <cassert>
#include <iostream>
#include <future>

int main()
{
    Map global
            { { "one", 1 },
              { "two", 2 },
              { "three", 3 } };

    auto background = async(worker, std::move(global));

    assert(global.empty());    // data now owned by the worker thread!

    global = background.get(); // await the result from the worker

    for (auto const& el: global) // now the data is owned by the main thread
        std::cout << el.first << ": " << el.second << "\n";
}

注意assert中间的main: 并发访问甚至是不可能的。

在 Coliru 上看到它。

于 2013-10-16T08:50:33.653 回答