使全局静态变量多线程安全

时间:2010-04-18 14:41:52

标签: c multithreading static-variables

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

4 个答案:

答案 0 :(得分:10)

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

__declspec( thread ) int tls_i = 1;

使tls_i存在于线程本地存储中(每个线程都有自己独立的此变量实例)。使用gcc时,语法为

__thread int tls_i;

您可能还想查看主题的wikipedia entry

答案 1 :(得分:4)

第一个问题:

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

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

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

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

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

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

您可能希望或最终必须为您的变量做类似的事情。你说它们是静态的这一事实可以改善一些事情。你只有一个文件要处理(除非你不小心传回 - 或指向那些变量的指针)。

答案 2 :(得分:3)

您需要的是 TLS(线程本地存储),也称为线程特定数据线程专用数据。这种机制可以保证每个线程访问自己独立的数据副本,而不必担心与其他线程同步访问。


使用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。

    LInux与GCC:     

      pthread_key_create():创建tls数据
      pthread_key_delete():将tls数据存入
      pthread_getspecific():获取tls'的值
      pthread_setspecific ():设置tls'的值
    转到联机帮助页以获取具体和详细信息。

答案 3 :(得分:1)

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

相关问题