使全局静态变量成为多线程安全的

时间:2021-04-03 23:35:10

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?

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

4 个解决方案

#1


10  

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),

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

__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

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

__thread int tls_i;

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

您可能还想查看有关该主题的*条目。

#2


4  

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:

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

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).

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

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).

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

#3


3  

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.

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


There are two methods to use TLS:

有两种方法可以使用TLS:

  1. implicit: using keyword

    隐式:使用关键字

    Windows: __declspec(thread) int tls_var = 10;

    Windows:__ declspec(thread)int tls_var = 10;

    Linux with GCC: __thread int tls_var = 10

    Linux与GCC:__thread int tls_var = 10

  2. explicit: using specific TLS related API

    显式:使用特定的TLS相关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.

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

    LInux with GCC:

    LInux与海湾合作委员会:

      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.

#4


1  

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

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

#1


10  

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),

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

__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

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

__thread int tls_i;

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

您可能还想查看有关该主题的*条目。

#2


4  

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:

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

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).

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

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).

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

#3


3  

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.

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


There are two methods to use TLS:

有两种方法可以使用TLS:

  1. implicit: using keyword

    隐式:使用关键字

    Windows: __declspec(thread) int tls_var = 10;

    Windows:__ declspec(thread)int tls_var = 10;

    Linux with GCC: __thread int tls_var = 10

    Linux与GCC:__thread int tls_var = 10

  2. explicit: using specific TLS related API

    显式:使用特定的TLS相关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.

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

    LInux with GCC:

    LInux与海湾合作委员会:

      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.

#4


1  

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

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