Ivy Lin
Ivy Lin

Reputation: 123

C pthread: Multiple Threads but only ONE thread is used

I am working on producer and consumer problems. I created one producer to put stuff into a bounded buffer and use multiple consumers to get data from the buffer. To check if every consumer is working I give each of them an ID and let them print it out.

Following are codes for creating multiple consumers.

#define CONSUMER_NUM 5;
pthread_t consumer[CONSUMER_NUM];
for(i=0;i<CONSUMER_NUM;i++){
    int t = i;
    pthread_create(&consumer[i],NULL,fun_consumer,(void*)&t);   
}   // pass i to the function fun_consumer to be an id of the thread

What I expected may look like:

Consumer 1
Consumer 2
Consumer 3
Consumer 4
Consumer 5

I understand that the output will usually not look like this due to the random execution of the threads. What I expected here is most the consumers will get into work. However, the truth is the program printed out like this:

Consumer 5
Consumer 5
Consumer 5
Consumer 5
Consumer 5

Only one consumer is used here. I tried "sleep", it can give me the output which I expected but caused slow execution. I am wondering if there is any better way to solve this problem?

Upvotes: 4

Views: 2543

Answers (2)

SergeyA
SergeyA

Reputation: 62553

You are giving every thread a pointer to local variable i. With each loop iteration i is changing - and by the time the threads are actually launched and ready loop is done, and i equals to 5 (last value).

However, this just one of the many potential outcomes. Your thread id could, indeed, read anything, as you have a classic data race in this code. You are accessing a variable from multiple threads, which is not protected in any way. Might even read 42, if luck has it this way.

Solution. Either dynamically create a new variable for every thread and pass an address of this variable (you'd need to delete in the thread to prevent memory leak), or convert integer variable to pointer and provide this value to thread. To do this (somewhat) portably, your i should actually be of a type uintptr_t, rather than unsigned int.

An example of how new variable can be created every time:

for (i=0 ; i<CONSUMER_NUM; ++i) {
    int* id = malloc(sizeof(int));
    *id = i;
    pthread_create(&consumer[i],NULL,fun_consumer, id);   
}
...
void* fun_consumer(void* arg) {
    int id = *(int*)(arg);
    free(arg)
    // rest of code

Upvotes: 4

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31143

You give them a reference to the variable i, which changes in the loop. It executes so quickly that every thread sees it as 5.

You are still getting five threads, you are just sending the number incorrectly.

Upvotes: 1

Related Questions