views:

959

answers:

3

In C, declaring a variable static in the global scope makes it a global variable. Is this global variable shared among threads or is it allocated per thread?

Update: If they are shared among threads, what is an easy way to make globals in a preexisting library unique to a thread/non-shared?

Update2: Basically, I need to use a preexisting C library with globals in a thread-safe manner.

+8  A: 

It's visible to the entire process, i.e., all threads. Of course, this is in practice. In theory, you couldn't say because threads have nothing to do with the C standard.

But all thread libraries I've ever used would have globals accessible to all threads.


Update 1:

Many thread libraries (pthreads, for one) will allow you to create thread-specific data, a means for functions to create and use data specific to the thread without having it passed down through the function.

So, for example, a function to return pseudo random numbers may want each thread to have an independent seed. So each time it's called it either creates or attaches to a thread-specific block holding that seed (using some sort of key).

This allows the functions to maintain the same signature as the non-threaded ones (important if they're ISO C functions for example) since the other solution involves adding a thread-specific pointer to the function call itself.

Another possibility is to have an array of globals of which each thread gets one, such as:

int fDone[10];
int idx;
: : :
for (i = 0; i < 10; i++) {
    idx = i;
    startThread (function, i);
    while (idx >= 0)
        yield();
}

void function () {
    int myIdx = idx;
    idx = -1;
    while (1) {
        : : :
    }
}

This would allow the thread function to be told which global variable in the array belongs to it.

There are other methods, no doubt, but short of knowing your target environment, there's not much point in discussing them.


Update 2:

The easiest way to use a non-thread-safe library in a threaded environment is to provide wrapper calls with mutex protection.

For example, say your library has a non-thread-safe doThis() function. What you do is provide a wrapper for it:

void myDoThis (a, b) {
    static mutex_t serialize;
    mutex_claim (&serialize);
    doThis (a, b);
    mutex_release (&serialize);
}

What will happen there is that only one thread at a time will be able to claim the mutex (and hence call the non-thread-safe function). Others will be blocked until the current one returns.

paxdiablo
Thanks. Updated question a bit.
jameszhao00
Sorry. Updated again...
jameszhao00
That's okay, James, I think I'm keeping up for now :-)
paxdiablo
mutex is not always an option, because library could store temporary data in global variables between several calls of one function. E.g. for calculating variance of some variable.
Kirill V. Lyadvinsky
That's a good point, @Kirill, but you can just move the serialization mutex up the execution hierarchy, for example, startDoThis(), myDoThis(), myDoThis(), ..., stopDoThis(), with the mutex claim in startDoThis() and release in stopDoThis(). But, at that point, I'd probably go looking for a better library, or write my own :-)
paxdiablo
If you have access to library source it would be better to write class wrapped and move all global variables in it. If you have no access to sources, then you can't know at what level of execution hierarchy you could use mutex.
Kirill V. Lyadvinsky
I have these follow up questions: 1. Are static variables stored on the stack itself similar to globals? If so, how are they protected to allow for only local class access? 2. In a multi threaded context, is the fear that this memory can be directly accessed by other threads/ kernel? or why cant we use static/global in multi process/ thread enviornment?
Swapna
@Swapna, that probably would have been better as a new question but: (1) no, threads generally have their own stack. (2) No, it's not the use of the memory that's the problem, it's the fact that thread A may try to use it halfway through an update by thread B (i.e., ehen it's in an inconsistent state).
paxdiablo
+1  A: 

C/C++ standard doesn't support threads. So all variables shared among threads. Thread support implemented in C/C++ runtime library which is not part of the standard. Runtime is specific for each implementation of C/C++. If you want to write portable code in C++ you could use boost interprocess library.

To declare thread local variable in Microsoft Visual Studio you could use Microsoft specific keyword __declspec( thread ).

Kirill V. Lyadvinsky
+1  A: 

As @Pax mentioned, static variables are visible to all threads. There's no C++ data construct associated with a particular thread.

However, on Windows you can use the TlsAlloc API to allocate index for a thread-specific data and put that index in a static variable. Each thread has its own slot which you can access using this index and the TlsGetValue and TlsSetValue. For more information, read about Using Thread Local Storage on MSDN.

Update: There's no way to make globals in a preexisting library be thread-specific. Any solutions would require you to modify the code as well to be aware that the data has thread affinity.

Franci Penov