6

我在 C 库中有全局静态变量,它们在多线程运行中生成异常。我需要以某种方式使它们安全(即,每个线程应该与这些变量的不同实例相关)。有什么推荐的方法吗?

4

4 回答 4

10

没有适用于所有 C 实现的标准方法,但存在特定于实现的解决方案。例如,使用 Microsoft 的编译器(请参阅文档),

__declspec( thread ) int tls_i = 1;

活在线程本地存储中tls_i(每个线程都有自己的这个变量的单独实例)。使用gcc,语法是

__thread int tls_i;

您可能还想查看有关该主题的维基百科条目

于 2010-04-18T14:45:33.597 回答
4

第一个问题:

  • 线程需要自己的变量副本吗?
  • 还是他们需要协调对单个共享副本的访问?

如果您需要前者,其他答案已经对“线程本地存储”提出了建议。

如果您需要后者,那么您需要以某种方式确保这些变量上有适当的互斥锁(互斥锁的范围是您面临的问题之一),并且线程都使用互斥锁并释放互斥锁。这更棘手。您甚至可能需要提供控制对变量的访问的函数。

标准变量errno可以是可修改的左值:

extern int *_errno_func(void);
#define errno (*(_errno_func)())

在线程应用程序(使用 -DREENTRANT 编译)中,会发生这种情况;在 MacOS X 上,这似乎是无论如何都会发生的事情(它们使用名称__error而不是_errno_func; 两者都在实现的命名空间中)。

您可能想要或最终不得不为您的变量做类似的事情。您说它们是静态的这一事实使情况有所改善。您只有一个文件要处理(除非您足够粗心,将指向这些变量的指针传回 - 或 on - )。

于 2010-04-18T14:55:32.870 回答
3

您需要的是TLS(Thread Local Storage),也称为线程特定数据线程私有数据。这种机制可以保证每个线程访问自己单独的数据副本,而不用担心与其他线程同步访问。


使用 TLS 有两种方法:

  1. 隐式:使用关键字

    Windows: __declspec(thread) int tls_var = 10;

    带有 GCC 的 Linux: __thread int tls_var = 10

  2. 显式:使用特定的 TLS 相关 API

    视窗:

      tlsAlloc():为tls数据分配内存
      tlsFree():释放tls数据的内存
      TlsSetValue():设置 tls 的值
      TlsGetValue():获取 tls 的值

    有关详细信息,请参阅 MSDN。

    带有 GCC 的 Linux:

      pthread_key_create() : 创建 tls 数据
      pthread_key_delete() : 破坏 tls 数据
      pthread_getspecific() : 获取 tls 的值
      pthread_setspecific (): 设置 tls 的值
    转到手册页以获取具体和详细的​​信息。

于 2010-09-08T05:56:47.837 回答
1

大多数编译器都有一些指定线程本地存储的方法。假设它可用,这就是你想要的。

于 2010-04-18T14:45:14.877 回答