我的程序使用std :: map存储一些信息以及一些非重复的键。此映射受一个std :: mutex保护。我在方法的开头使用std :: lock_guard进行范围锁定,这些方法在地图上执行 .insert 或 .erase(with iterator)。
我不是仅在我执行 .find 的方法中锁定互斥锁,而是使用该迭代器来获取我需要的信息。如果我只是执行 .find ,我是否需要保护地图?
问题是当我连续几个小时运行我的程序时,在我的程序崩溃的某个时刻会产生很多.insert和.erase操作。
(?:(.*\r?\n)(.*\r?\n)){8}\K
当查找项目并通过迭代器删除它的代码受锁定的互斥锁保护时,我不明白它是如何崩溃的。这发生在android。
同样的代码在Tizen崩溃
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc
Cause: null pointer dereference
#00 pc 00063d62 lib/arm/libgnustl_shared.so (_ZSt28_Rb_tree_rebalance_for_erasePSt18_Rb_tree_node_baseRS_+137)
希望找到一些指示。
答案 0 :(得分:1)
当多个线程访问同一个对象并且这些线程中至少有一个修改了对象的值时,程序会有数据竞争。因此,问题中的代码具有数据竞争,因为读者可以在另一个线程正在修改数据时访问数据。具有数据争用的程序具有未定义的行为。
数据竞争的修复是通过使用原子访问(硬)或使用互斥(更容易,但可能更慢)来防止多个同时访问同一对象。这里最简单的解决方案是使用相同的互斥锁保护树上的每个操作。
即使这样,阻止数据竞争不保证正确性。例如:
int sz = my_vector.size();
for (int i = 0; i < sz; ++i)
// do something with my_vector[i]
在size()
和operator[]
中使用互斥锁是不够的;另一个线程可能会从向量中删除一个元素,因此sz
会出错,并且循环将离开向量的末尾。