【发布时间】:2020-08-24 19:56:28
【问题描述】:
我知道std::map 类在两个线程的读写中是线程不安全的。但是在多个线程中插入可以吗?
void writeMap()
{
for (int i = 0; i < 1000; i++)
{
long long random_variable = (std::rand()) % 1000;
std::cout << "Thread ID -> " << std::this_thread::get_id() << " with looping index " << i << std::endl;
k1map.insert(std::make_pair(i, new p(i)));
}
}
int main()
{
std::srand((int)std::time(0));
for (int i = 0; i < 1000; ++i)
{
long long random_variable = (std::rand()) % 1000;
std::thread t(writeMap);
std::cout << "Thread created " << t.get_id() << std::endl;
t.detach();
}
return 0;
}
无论我尝试多少次,就像这样的代码运行正常。
【问题讨论】:
-
一般来说,没有。从纯多线程的角度来看,没有对象可以保护自己免受两个线程的无序/并发访问,并且该逻辑扩展到意味着可以修改对象的对象的非静态成员在被多个线程直接使用时无法保护该对象线程。这就是为什么调用代码(在您的情况下,调用
std::map::insert()的代码)必须处理同步(使用互斥锁等) - 除非以这种方式受到保护,否则被调用函数不能提供绝对保证。 -
一般规则是写入不能与任何其他读取或写入同时发生。所以两个写不能并发,需要同步。
std::map::insert是一个写操作,因为它(可能)修改了映射。 -
理论上是这样,但是为什么实际代码运行没有任何问题,请解释
-
当行为未定义时,对发生的事情没有明确的约束。一个完全可能的结果是,在您的测试中,发生的事情显示为“运行没有问题”。同样可能的结果是它通过了您的测试,但在客户使用时出现故障。
-
运气好。它可能是 std 库实现的编码和/或 CPU 架构的组合和/或当两个线程在同一个内核上运行时不会出现一些并发问题,但是如果突然将它们安排到不同的内核上,那么错误可能会浮出水面和/或等等......
标签: c++ c++11 stl thread-safety