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

发布于 2024-08-29 15:51:57 字数 81 浏览 4 评论 0原文

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

I have global static variables in a C library, which generate exceptions in a multithread run. I need to make them safe in some way (i.e., each thread should relate to a different instance of these variables). Any recommended methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

神仙妹妹 2024-09-05 15:51:57

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

__declspec( thread ) int tls_i = 1;

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

__thread int tls_i;

您也可以想要查看有关该主题的维基百科条目

There is no standard way that works across all C implementations, but implementation-specific solutions exist. For example, with Microsoft's compiler (see the docs),

__declspec( thread ) int tls_i = 1;

makes tls_i live in thread-local storage (each thread has its own separate instance of this variable). With gcc, the syntax is

__thread int tls_i;

You may also want to check the wikipedia entry on the subject.

滥情空心 2024-09-05 15:51:57

第一个问题:

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

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

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

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

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

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

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

First question:

  • do the threads need their own copies of the variables?
  • or do they need to coordinate access to a single shared copy?

If you need the former, the other answers have made suggestions about 'thread-local storage'.

If you need the latter, then somehow or another you need to ensure there's an appropriate mutex on those variables (the scope of the mutex is one of the issues you face), and that the threads all use the mutex, and release the mutex. This is trickier. It may even be that you need to provide functions that control access to the variables.

The standard variable errno can be a modifiable lvalue:

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

In a threaded application (compiled with -DREENTRANT), this is what happens; on MacOS X, it appears to be what happens anyway (they use the name __error instead of _errno_func; both are in the implementation's namespace).

You may want to, or end up having to, do something similar for your variables. The fact that you say they are static improves things a bit. You only have one file to deal with (unless you are careless enough to pass back - or on - pointers to those variables).

短叹 2024-09-05 15:51:57

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


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

    Linux 与 GCC:

      pthread_key_create():创建tls数据
      pthread_key_delete():销毁tls数据
      pthread_getspecic():获取tls的值
      pthread_setspecic():设置tls的值

    请参阅联机帮助页以获取具体详细信息。

What you needed is TLS(Thread Local Storage), which is also known as thread-specific data or thread-private data. This mechanism can guarantee each thread to access its own separate copy of data, without worrying about synchronizing access with other threads.


There are two methods to use TLS:

  1. implicit: using keyword

    Windows: __declspec(thread) int tls_var = 10;

    Linux with GCC: __thread int tls_var = 10

  2. explicit: using specific TLS related API

    Windows:

      TlsAlloc(): allocate memory for tls data
      TlsFree(): free the memory of tls data
      TlsSetValue(): set tls' value
      TlsGetValue(): get tls' value

    Please refer to MSDN for detailed information.

    LInux with GCC:

      pthread_key_create(): create the tls data
      pthread_key_delete(): destory the tls data
      pthread_getspecific(): get tls' value
      pthread_setspecific(): set tls' value

    Turn to manpage for specific and detailed information.

大姐,你呐 2024-09-05 15:51:57

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

Most compilers have some way of designating thread-local storage. Assuming it's available, that's what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文