简体   繁体   中英

Why thread specific data is required in pthread?

all the threads share memory location. For example a global variable changes in one thread will reflect in another thread. Since each thread has its own stack, the local variables that are created inside the thread is unique. In this case, why do we need to go for thread specific data mechanism?. Can't it be achieved by auto storage varibles inside the thread function ?

Kindly clarify!!!.

BR Rj

Normal globals are shared between threads. Local variables are specific to a particular invocation of a function. If you want something that (for example) is visible to a number of functions running in the same thread, but unique to that thread, then thread specific data is what you're looking for.

It's not required but it's rather handy. Some functions like rand and strtok use static storage duration information which is likely to be problematic when shared among threads.

Say you have a random number function where you want to maintain a different sequence (hence seed) for each thread. You have two approaches.

You can use something like the kludgy:

int seed;
srand (&seed, time (NULL));
int r = rand_r (void *seed);

where the seed has to be created by the caller and passed in each time.

Or you can use the rather nicer, ISO-compliant:

srand (time (NULL));
int r = rand();

that uses thread-local storage to maintain a thread-specific seed. Similarly with the information used by strtok regarding the locations within the string it's processing.

That way, you don't have to muck about with changing your code between threaded and non-threaded versions.

Now you could create that information in the thread function but how is the rand function going to know about it's address without it being passed down. And what if rand is called 87 stack levels down? That's an awful lot of levels to be transferring a pointer through.

And, even if you do something like:

void pthread_fn (void *unused) {
    int seed;
    rand_set_seed_location (&seed);
    :
}

and rand subsequently uses that value regardless of how deep it is in the stack, that's still a code change from the standard. It may work but so may writing an operating system in COBOL. That doesn't make it a good idea :-)

是的,堆栈是分配线程本地存储的一种方式(包括特定线程本地堆分配的句柄)。

The best example for thread specific data is the " errno ". When a call to some function in c library failed, the errno is set, and you can check it out to find the reason of the failure. If there's no thread specific data, it's impossible to port these functions to multi-thread environment because the errno could be set by other threads before you check it.

As a general rule, most uses of TSD should be avoided in new APIs. If a function needs some information, it should be passed to it.

However, sometimes you need TSD to 'paper over' an API defect. A good example is 'gmtime'. The 'gmtime' function returns a pointer to a structure that is valid until the next call to 'gmtime'. But that would make 'gmtime' awfully hard to use in a multi-threaded program. What if some library called 'gmtime' when you didn't expect it, trashing your structure? One simple workaround is make the structure returned thread-specific. (The long-term solution, of course, is to create a more suitable API such as 'gmtime_r'.)

One case where it's perfectly reasonable to use TSD in new designs is for information that won't be accessed frequently that would clutter the API. For example, if a critical error is discovered, it might be nice to log certain context information from higher-level code (Which client were you serving? What command did they send?). Your choices are basically to pass this context information from function to function to function (which isn't even always possible if some of the functions are outside your control) or to store it in TSD.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM