【问题标题】:Making global static variables multithread safe使全局静态变量多线程安全
【发布时间】:2010-04-18 14:41:52
【问题描述】:

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

【问题讨论】:

    标签: c multithreading static-variables


    【解决方案1】:

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

    __declspec( thread ) int tls_i = 1;
    

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

    __thread int tls_i;
    

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

    【讨论】:

    • @giladsah:阅读答案的后半部分!
    • @giladsah,当然,__thread 关键字正如我刚刚在我的回答中所说的(我还指出了关于线程本地存储的gcc 文档页面以获取更多详细信息)。
    【解决方案2】:

    第一个问题:

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

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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


      使用 TLS 有两种方法:

      1. 隐式:使用关键字

        Windows: __declspec(thread) int tls_var = 10;

        带有 GCC 的 Linux: __thread int tls_var = 10

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

        Windows:

          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的值
        转到手册页以获取具体和详细的​​信息。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-24
          • 1970-01-01
          • 2011-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多