如何为每个实例提供非静态线程局部变量 [英] How can I have non-static thread-local variable for each instance

查看:70
本文介绍了如何为每个实例提供非静态线程局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题本身:

class B{/*...*/};
class A {
    /* members */
    NON-static thread_local B var; // and a thread_local variable here
    ret_t method(/* args */);
};

我希望var每个线程和每个实例独立存在.

I want var to exist independently each thread and each instance.

较大(完整)的问题:

A的实例在线程之间共享. B是调用A::method所必需的一些资源,它必须相对于线程是独立的,以避免出现竞争状况(即A::method必须具有对var的写访问权").对于A的不同实例,相应的B也不同.

Instances of A are shared across threads. B is some resource necessary to call A::method, and it must be independent with respect to threads to avoid race condition (that is, A::method must have "write access" to var). And the corresponding B are different for different instances of A.

我想出的一种不完全令人满意的方法是有一些容器(例如std::unordered_map<THREAD_IDENTIFIER_TYPE, B>)来存储每个实例中与每个thread相对应的每个var.但是,这既不限制跨线程对var的访问,也不阻止整个容器被修改. (因此,要求开发人员足够小心以编写安全的代码.)

One not fully satisfactory approach I came up with is to have some container (say std::unordered_map<THREAD_IDENTIFIER_TYPE, B>) to store each var corresponding to each thread per instance. However, this neither limit access to vars across threads nor prevent the whole container from being modified. (So that require developer to be careful enough to write safe code.)

我在SO上见过关于Java ThreadLocal keyword(?)的一些文章,但似乎都没有提供真正可行的想法.有什么建议吗?

I've seen a few post on java ThreadLocal keyword(?) on SO, but none of them seem to provide idea that really works. Any suggestion?

推荐答案

您不能具有声明为thread_local的非静态成员.请参见 cppreference .特别是:

You can't have a non-static member declared thread_local. See cppreference. In particular:

thread_local关键字仅适用于在命名空间范围内声明的对象,在块范围内声明的对象以及静态数据成员.

the thread_local keyword is only allowed for objects declared at namespace scope, objects declared at block scope, and static data members.

如果您不想使用pthreads(在Windows上为tricky),则只有容器是您的唯一选择.

If you don't want to use pthreads (tricky on Windows), some container is your only option.

一个选择是std::unordered_map<THREAD_IDENTIFIER_TYPE, B>的变体. (您可以编写一个类来包装它并使用互斥锁保护地图.)

One choice is a variant of std::unordered_map<THREAD_IDENTIFIER_TYPE, B>. (You could write a class to wrap it and protect the map with a mutex.)

另一个吸引人的选择是Athread_local静态成员,该成员将A*映射到B可以避免使用锁.

Another initially attractive option is a thread_local static member of A which maps A* to B will avoid any need for locks.

class A {
    static thread_local std::unordered_map<A*, B> s_B;
    ....
};

用法:

void A::foo() {
    B& b = s_B[this];  // B needs to be default constructable.
    ...

问题是您需要某种方法从s_B映射中删除元素.如果A对象实际上已锁定到特定线程,或者如果您有某种方法可以调用另一个线程上的函数,那么这并不是什么大问题-但这也不是完全无关紧要的. (您可能会发现为A使用唯一的标识符(这是一个递增的64位计数器)更安全-这样,在销毁A对象和消息以删除B来自所有正在处理的地图.)

The catch is that you need some way to remove elements from the s_B map. That's not too much of a problem if A objects are actually locked to a particular thread, or if you have some way to invoke functions on another thread - but it's not entirely trivial either. (You may find it safer to use a unique identifier for A which is an incrementing 64-bit counter - that way there is much less risk of the identifier being reused between destroying the A object and the message to remove the B from all the maps being processed.)

这篇关于如何为每个实例提供非静态线程局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆