使全局静态变量多线程安全
-
27-09-2019 - |
题
我在C库中具有全局静态变量,该变量在多线程运行中生成异常。我需要以某种方式使它们安全(即,每个线程都应与这些变量的不同实例有关)。有建议的方法吗?
解决方案
在所有C实施中都没有标准方法,但是存在特定于实施的解决方案。例如,使用Microsoft的编译器(请参阅 文档),
__declspec( thread ) int tls_i = 1;
制作 tls_i
实时在线程 - 本地存储中(每个线程都有其自己的独立实例)。和 海湾合作委员会, ,语法是
__thread int tls_i;
您可能还想检查 Wikipedia条目 就此主题而言。
其他提示
第一个问题:
- 线程需要自己的变量副本吗?
- 还是他们需要协调对单个共享副本的访问?
如果您需要前者,其他答案就提出了有关“线程本地存储”的建议。
如果需要后者,则需要以某种方式确保这些变量上有适当的静音(静音的范围是您所面临的问题之一),并且线程都使用了sutex,并释放了mutex。这很棘手。甚至可能是您需要提供控制对变量的访问的功能。
标准变量 errno
可以是可修改的lvalue:
extern int *_errno_func(void);
#define errno (*(_errno_func)())
在螺纹应用程序(用-drentrant编译)中,这就是发生的事情。在MacOS X上,似乎无论如何都会发生(他们使用名称 __error
代替 _errno_func
;两者都在实现的命名空间中)。
您可能需要或最终必须为变量做类似的事情。您说它们是静态的事实可以有所改善。您只有一个文件可以处理(除非您不小心可以向这些变量传递给或启用指针)。
您需要的是 TLS(线程本地存储), ,也称为 特定于线程的数据 或者 线程私人数据. 。该机制可以保证每个线程访问其自己的单独的数据副本,而不必担心将访问与其他线程同步。
有两种使用TLS的方法:
隐式:使用关键字
视窗: __declSpec(thread)int tls_var = 10;
Linux与GCC: __ thread int tls_var = 10
显式:使用特定TLS相关的API
视窗:
- tlsalloc(): 为TLS数据分配内存
- tlsfree(): 免费记忆TLS数据
- tlssetValue(): 设置TLS的值
- tlsgetValue(): 获取TLS的价值
请参阅MSDN以获取详细信息。
Linux与GCC:
- pthread_key_create(): :创建TLS数据
- pthread_key_delete(): :destory TLS数据
- pthread_getspecific(): :获取TLS的价值
- pthread_setspefific():设置TLS的值
大多数编译器都有某种方式指定线程本地存储。假设它可用,这就是您想要的。