How do I create a global variable that is thread-specific in C using POSIX threads?

后端 未结 3 768
[愿得一人]
[愿得一人] 2021-01-31 21:32

I am learning about POSIX threads and I have come to the section on Thread Specific Data. The book does an excellent example using a file descriptor. However, I wanted to do the

相关标签:
3条回答
  • 2021-01-31 21:39

    This is not an answer, but a side note:

    If you are working on Linux-specific code, you can use the __thread keyword. Essentially,

    static __thread int counter = 5;
    

    creates a different counter variable for each thread, initialized to value 5 whenever a new thread gets created. Such code is future-compatible with C11, since C11 standardized the same semantics using the _Thread_local keyword. This is much saner than the POSIX thread-specific functions (which have implementation-specific limits, and are quite cumbersome compared to the __thread keyword), on all architectures using C, except those that have declared C99 and later "standard non grata" (i.e., Microsoft).

    See the Thread-Local Storage chapter in GCC documentation for details.

    0 讨论(0)
  • 2021-01-31 21:58

    The purpose of TLS (thread-local storage) is to provide an defined mechanism whereby code can retrieve thread-specific data stored in a database accessed by a all-threads-known shared key. Your code is storing the same data in TLS: the address of a single global variable). Therefore when a thread requests this data using the tls-key, they will all get back the same address.

    I think you intend your code to do something like this:

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #define NUMTHREADS 4
    
    pthread_key_t glob_var_key;
    
    void do_something()
    {
        //get thread specific data
        int* glob_spec_var = pthread_getspecific(glob_var_key);
        printf("Thread %d before mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var);
        *glob_spec_var += 1;
        printf("Thread %d after mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var);
    }
    
    void* thread_func(void *arg)
    {
        int *p = malloc(sizeof(int));
        *p = 1;
        pthread_setspecific(glob_var_key, p);
        do_something();
        do_something();
        pthread_setspecific(glob_var_key, NULL);
        free(p);
        pthread_exit(NULL);
    }
    
    int main(void)
    {
        pthread_t threads[NUMTHREADS];
        int i;
    
        pthread_key_create(&glob_var_key,NULL);
        for (i=0; i < NUMTHREADS; i++)
            pthread_create(threads+i,NULL,thread_func,NULL);
    
        for (i=0; i < NUMTHREADS; i++)
            pthread_join(threads[i], NULL);
    
        return 0;
    }
    

    Output

    Thread 2625536 before mod value is 1
    Thread 741376 before mod value is 1
    Thread 3162112 before mod value is 1
    Thread 3698688 before mod value is 1
    Thread 2625536 after mod value is 2
    Thread 741376 after mod value is 2
    Thread 3162112 after mod value is 2
    Thread 3698688 after mod value is 2
    Thread 2625536 before mod value is 2
    Thread 741376 before mod value is 2
    Thread 3162112 before mod value is 2
    Thread 3698688 before mod value is 2
    Thread 2625536 after mod value is 3
    Thread 741376 after mod value is 3
    Thread 3162112 after mod value is 3
    Thread 3698688 after mod value is 3
    
    0 讨论(0)
  • 2021-01-31 22:01

    In general, what you're looking for is "thread local storage". Here are a few links:

    • http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frzahw%2Frzahwex1.htm

    • http://en.wikipedia.org/wiki/Thread-local_storage

    Choosing pthread_getspecific() is correct. Here's a good example:

    • http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_34.htm

    Please review the above example: I think it will point you to the problem ... or suggest a good alternative.

    IMHO...

    0 讨论(0)
提交回复
热议问题