在非线程安全容器中访问指针指向的值(线程安全映射中的条目)是否可以?

is it ok to access value(entry in thread safe map) pointed by pointer inside non-thread safe container?

例如,

// I am using thread safe map from
// code.google.com/p/thread-safe-stl-containers
#include <thread_safe_map.h>

class B{
  vector<int> b1;
};

//Thread safe map
thread_safe::map<int, B> A;
B b_object;
A[1] = b_object;

// Non thread safe map.
map<int, B*> C;
C[1] = &A[1].second;

那么下面的操作仍然是线程安全的吗?

Thread1:
for(int i=0; i<10000; i++) {
  cout << C[1]->b1[i];
}

Thread2:
for(int i=0; i<10000; i++) {
  C[1]->b1.push_back(i);
}

上面的代码有没有问题?如果是,我该如何解决?

是否可以访问非线程安全容器中指针指向的值(线程安全映射中的条目)?

一般来说,只要所有线程都可以从多个线程访问 STL 容器:

  • 从同一容器读取

  • 以线程安全的方式修改元素

您不能从一个线程 push_back(或 eraseinsert 等)并从另一个线程读取。假设您正在尝试访问线程 1 中的元素,而线程 2 中的 push_back 正在重新分配向量的存储空间。这可能会使应用程序崩溃,可能 return 产生垃圾(如果幸运的话,也可能有效)。

第二个要点适用于这样的情况:

std::vector<std::atomic_int> elements;

// Thread 1:
elements[10].store(5);

// Thread 2:
int v = elements[10].load();

在这种情况下,您同时读取和写入一个原子变量,但向量本身没有被修改——只有它的元素被修改了。

编辑: 使用 thread_safe::map 在您的情况下不会改变任何内容。虽然可以修改地图,但修改其元素则不行。将 std::vector 放入线程安全的集合中并不会自动使其成为线程安全的。

不,你在那里做的事不安全。 thread_safe_map 的实现方式是在每次函数调用期间锁定:

//Element Access
T & operator[]( const Key & x ) { boost::lock_guard<boost::mutex> lock( mutex ); return storage[x]; }

一旦访问函数结束,锁就会被释放,这意味着您通过返回的引用所做的任何修改都没有保护。

除了不完全安全之外,此方法非常慢。

这里提出了一种安全(呃)、高效但高度实验性的容器锁定方法:https://github.com/isocpp/CppCoreGuidelines/issues/924 源代码在这里 https://github.com/galik/GSL/blob/lockable-objects/include/gsl/gsl_lockable(无耻的自我推销免责声明)。