Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making global static variables multithread safe

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?

like image 713
giladsah Avatar asked Apr 18 '10 14:04

giladsah


People also ask

Are static global variables thread safe?

Static variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.

Can we use static variable in multithreading?

Static variable is a shared resource, which can be used to exchange some information among different threads. And we need to be careful while accessing such a shared resource. Hence, we need to make sure that the access to static variables in multi-threaded environment is synchronized. This is a correct statement.


3 Answers

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.

like image 148
Alex Martelli Avatar answered Nov 11 '22 15:11

Alex Martelli


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

like image 25
Jonathan Leffler Avatar answered Nov 11 '22 14:11

Jonathan Leffler


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.
like image 38
ylzhang Avatar answered Nov 11 '22 15:11

ylzhang