I am programming using pthread. I need a global variable that it has different value for different threads. And threads will use same function to deal with this variable, such as change its value. If one thread change its value, the value in other threads would not be changed. So I tried to use thread specific data, and wrote a example. I need wrap the pthread operations in functions. For exapmle: setspecific(), changedata, printdata(), create_key(), delete_key(), etc.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_key_t key;
pthread_key_t key2;
struct test_struct {
int i;
float k;
}struct_data;
int temp;
int setspecificvar () { /* Set specific data for threads */
pthread_setspecific (key, &struct_data);
pthread_setspecific (key2, &temp);
return 0;
}
int changedata (int i, float k, int tempvar) { /* Change specific data for threads */
temp = tempvar;
struct_data.i = i;
struct_data.k = k;
return 0;
}
int printdata (int t) { /* print specific data for threads */
printf ("The addres in child%d returned from pthread_getspecific(key):0x%p\n", \
t, (struct test_struct *)pthread_getspecific(key));
printf ("The value of members in structure bound to \"key\" in child%d:\nstruct_data.i:%d\nstruct_data.k: %f\n", \
t, ((struct test_struct *)pthread_getspecific (key))->i, \
((struct test_struct *)pthread_getspecific(key))->k);
printf ("------------------------------------------------------\n");
printf ("The addres in child%d returned from pthread_getspecific(key2):0x%p\n", \
t, (int *)pthread_getspecific(key2));
printf ("The value of \"temp\" bound to \"key2\" in child%d:%d\n", \
t, *((int *)pthread_getspecific(key2)));
return 0;
}
void *child1 (void *arg)
{
setspecificvar ();
changedata(10, 3.141500, 110); /* Should not change the data in child2 */
printdata(1);
}
void *child2 (void *arg)
{
/* sleep (2); */
setspecificvar ();
changedata(12, 2.141500, 120); /* Should not change the data in child1 */
printdata(2);
changedata (122, 22.141500, 1220); /* Should not change the data in child1 */
printdata (2);
}
int create_key () {
pthread_key_create (&key, NULL);
pthread_key_create (&key2, NULL);
return 0;
}
int delete_key () {
pthread_key_delete (key);
pthread_key_delete (key2);
return 0;
}
int main (void)
{
pthread_t tid1, tid2;
create_key ();
pthread_create (&tid1, NULL, (void *)child1, NULL);
pthread_create (&tid2, NULL, (void *)child2, NULL);
pthread_join (tid1, NULL);
pthread_join (tid2, NULL);
delete_key ();
return 0;
}
I create two threads. When I make one thread sleep 2 seconds. I get correct answer.
The addres in child1 returned from pthread_getspecific(key):0x0x8049c98
The value of members in structure bound to *"key" in child1*:
*struct_data.i:10
struct_data.k: 3.141500*
------------------------------------------------------
The addres in child1 returned from pthread_getspecific(key2):0x0x8049ca0
The value of "temp" bound to *"key2" in child1*:110
The addres in child2 returned from pthread_getspecific(key):0x0x8049c98
The value of members in structure bound to "key" in child2:
struct_data.i:12
struct_data.k: 2.141500
------------------------------------------------------
The addres in child2 returned from pthread_getspecific(key2):0x0x8049ca0
The value of "temp" bound to "key2" in child2:120
The addres in child2 returned from pthread_getspecific(key):0x0x8049c98
The value of members in structure bound to "key" in child2:
struct_data.i:122
struct_data.k: 22.141500
------------------------------------------------------
The addres in child2 returned from pthread_getspecific(key2):0x0x8049ca0
The value of "temp" bound to "key2" in child2:1220
when I comment /* sleep(2); */ , I get uncorrect answer.
The addres in child1 returned from pthread_getspecific(key):0x0x8049c54
The addres in child2 returned from pthread_getspecific(key):0x0x8049c54
The value of members in structure bound to "key" in child2:
*struct_data.i:12
struct_data.k: 2.141500*
The value of members in structure bound to *"key" in child1*:
struct_data.i:12
struct_data.k: 2.141500
------------------------------------------------------
The addres in child1 returned from pthread_getspecific(key2):0x0x8049c5c
The value of "temp" bound to *"key2" in child1*:120
------------------------------------------------------
The addres in child2 returned from pthread_getspecific(key2):0x0x8049c5c
The value of "temp" bound to "key2" in child2:120
The addres in child2 returned from pthread_getspecific(key):0x0x8049c54
The value of members in structure bound to "key" in child2:
struct_data.i:122
struct_data.k: 22.141500
------------------------------------------------------
The addres in child2 returned from pthread_getspecific(key2):0x0x8049c5c
The value of "temp" bound to "key2" in child2:1220
I want get the right result without sleep a thread. One thread should not wait for the other thread to finish to call pthread_setspecific() , right? What should I do? Thanks for your consideration.Did I right to define struct_data as global variable? Anyone can help me?
Here you explicitly set both
key
andkey2
to the same value in each thread so it shouldn't be surprising that it has the same value in each thread. Try setting it to a different value in each thread and then it will have different values in each thread.A common pattern is this:
Call
pthread_getspecific
. If it returns non-NULL, use that pointer.If it returns NULL, use dynamically allocate a new instance of the thread-specific object. Call
pthread_setspecific
to ensure the next call topthread_getspecific
from this thread returns that same object.In the
pthread_key_create
call, be sure to register a destructor that frees the instance of the thread-specific object when a thread goes away.This will give each thread its own instance of a structure.
For example:
This actually sets a different value in each thread. And this:
This actually uses the thread-specific data.