问题本身:
class B{/*...*/}; class A { /* members */ NON-static thread_local B var; // and a thread_local variable here ret_t method(/* args */); };
我想var
独立存在每个线程和每个实例.
更大(完整)的问题:
实例A
跨线程共享.B是调用所需的一些资源A::method
,它必须是独立的线程才能避免竞争条件(即A::method
必须具有"写访问权限" var
).B
对于不同的实例,相应的是不同的A
.
我提出的一个不完全令人满意的方法是让一些容器(比如说std::unordered_map
)存储每个var
对应于每个thread
实例的容器.但是,这既不限制var
跨线程访问s也不会阻止整个容器被修改.(因此,要求开发人员要小心,以便编写安全的代码.)
我在SO上看过一些关于java ThreadLocal关键字(?)的帖子,但它们似乎都没有提供真正有用的想法.有什么建议吗?
您不能声明非静态成员thread_local
.见cppreference.特别是:
该
thread_local
关键字仅允许在命名空间范围内声明的对象,在块范围内声明的对象和静态数据成员.
如果你不想使用pthreads(在Windows上很棘手),一些容器是你唯一的选择.
一种选择是变体std::unordered_map
.(您可以编写一个类来包装它并使用互斥锁保护地图.)
另一种最初有吸引力的选择是一个thread_local
静态成员的A
它映射A*
到B
将避免任何需要锁.
class A { static thread_local std::unordered_map s_B; .... };
用法:
void A::foo() { B& b = s_B[this]; // B needs to be default constructable. ...
问题是你需要一些方法来从s_B
地图中删除元素.如果A
对象实际上被锁定到特定线程,或者如果你有某种方法可以在另一个线程上调用函数,那么这不是太大的问题- 但它也不是完全无关紧要的.(您可能会发现使用一个A
增量64位计数器的唯一标识符更安全- 这样,在销毁A
对象和消息之间重复使用标识符的风险要小得多,以便B
从正在处理的所有地图中删除它. )