Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使全局静态变量多线程安全_C_Multithreading_Static Variables - Fatal编程技术网

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

C 使全局静态变量多线程安全,c,multithreading,static-variables,C,Multithreading,Static Variables,我在C库中有全局静态变量,它在多线程运行中生成异常。我需要以某种方式使它们安全(即,每个线程应该与这些变量的不同实例相关)。有什么推荐的方法吗?大多数编译器都有指定线程本地存储的方法。假设它是可用的,这就是您想要的。没有标准的方法可以在所有C实现中工作,但存在特定于实现的解决方案。例如,使用Microsoft的编译器(请参阅) 使tls_i活在线程本地存储中(每个线程都有自己单独的此变量实例)。对于,语法是 __thread int tls_i; 您可能还需要查看有关该主题的信息。第一个问题:

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

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

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

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

__thread int tls_i;
您可能还需要查看有关该主题的信息。

第一个问题:

  • 线程是否需要自己的变量副本
  • 或者他们是否需要协调对单个共享副本的访问
如果您需要前者,其他答案对“线程本地存储”提出了建议

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

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

extern int *_errno_func(void);
#define errno (*(_errno_func)())
在线程应用程序(使用-drentrant编译)中,会发生这种情况;在MacOS X上,似乎无论如何都会发生这种情况(它们使用名称
\u error
而不是
\u errno\u func
;两者都在实现的命名空间中)


您可能想要,或者最终不得不,对您的变量执行类似的操作。事实上,你说它们是静态的,这会稍微改善一些情况。您只需要处理一个文件(除非您太粗心而将返回或指向这些变量的指针)。

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


使用TLS有两种方法:

  • 隐式:使用关键字

    窗口:\u declspec(线程)int tls\u var=10

    带GCC的Linux:\uuuu线程int tls\u var=10

  • 明确:使用特定的TLS相关API

    窗口:
      TlsAlloc():为tls数据分配内存
    TlsFree():释放tls数据的内存TlsSetValue():设置tls的值TlsGetValue():获取tls的值

    有关详细信息,请参阅MSDN

    带GCC的LInux:
      pthread\u key\u create():创建tls数据
    pthread\u key\u delete():销毁tls数据pthread\u getspecific()获取tls值pthread\u setspecific:设置tls值 有关具体和详细信息,请转到手册页


  • @吉拉德萨:读下半部分的答案@giladsah,当然,正如我刚才在回答中所说的那样,
    \uu线程
    关键字(我还指向了一个关于线程本地存储的
    gcc
    doc页面以了解更多详细信息)。
    extern int *_errno_func(void);
    #define errno (*(_errno_func)())