转自:
0
I am currently learing all around POSIX threads (pthread). I now have created a simple program which increased a shared value by 7 until above 10000 then it should signal a condition to the next thread which decreases it by 3 until under 1000. At last it should divide the result through 2 and main should output the result. |
my code
pthread_t threads[3];pthread_cond_t cond_a, cond_b;pthread_mutex_t mutex;int counter;void * worker_one();void * worker_two();void * worker_three();int main(int argv, const char ** argc) { counter = 0; pthread_cond_init(&cond_a, NULL); pthread_cond_init(&cond_b, NULL); pthread_mutex_init(&mutex, NULL); pthread_create(&threads[0], NULL, worker_one, NULL); pthread_create(&threads[1], NULL, worker_two, NULL); pthread_create(&threads[2], NULL, worker_three, NULL); pthread_join(threads[0], NULL); pthread_join(threads[1], NULL); pthread_join(threads[2], NULL); printf("Value started at %d and ends with %d.\n", 0, counter); return 0;}void * worker_one() { printf("Worker one started.\n"); pthread_mutex_lock(&mutex); printf("Worker one starting work.\n"); while (counter < 10000) { counter += 7; } pthread_cond_signal(&cond_a); printf("Worker one finished work with: %d.\n", counter); pthread_mutex_unlock(&mutex); pthread_exit(NULL);}void * worker_two() { printf("Worker two started.\n"); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond_a, &mutex); printf("Worker two starting work.\n"); while (counter > 1000) counter -= 3; printf("Worker two finished work with: %d.\n", counter); pthread_cond_signal(&cond_b); pthread_mutex_unlock(&mutex); sleep(1); pthread_exit(NULL);}void * worker_three() { printf("Worker three started.\n"); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond_b, &mutex); printf("Worker three starting work.\n"); counter /= 2; printf("Worker three finished work with: %d.\n", counter); pthread_mutex_unlock(&mutex); pthread_exit(NULL);}
For some reason the whole execution hangs around the first thread. The signal is also fired but thread two does not react.
Can somebody tell me what I am doing wrong?
| Could somebody tell me why down vote? – May 29 '13 at 16:23 | ||
| I've moved the code from gist to SO. Don't just link to code on an external site, please include relevant code in the question. – May 29 '13 at 16:25 | ||
| ok did not knew anything about this – May 29 '13 at 16:25 |
6 accepted
I have answered a similar question here: . The problem is that you wait before even testing the condition you want to wait for is true. What happens is that thread 1 signals before thread 2 is waiting, therefore the signal is lost and thread 2 will be waiting forever. In order to avoid this, first test what you want to wait for, then wait only if it's not here. EDIT: Ok, here is a possible solution with only one mutex and one condtion (untested) Thread 1: |
pthread_mutex_lock(&mutex); while(thread_1_should_work == false){ // wait until the condition is satisfied pthread_cond_wait(&cond, &mutex); }//at this point, we owe the mutex and we know thread_1_should_work is true; // do work thread_1_shoudl_work = false; thread_2_should_work = true; pthread_cond_broadcast(&cond); //wake up any waiting thread (if it's not their turn, they'll call wait again)pthread_mutex_unlock(&mutex);
@bodokaiser: you'll have to make up a variable, but a simple boolean flag will do. Spurious wakeups are a reality unfortunately. – May 29 '13 at 16:35 | |
@sixlettervariables so the main idea of conditions are just some more specific mutex signaling (with out the actual locking). Is this correct? – May 29 '13 at 16:36 | |
Yes, in your case is thread_is_working flag would work (except that it has more than 6 letters :) I think the answer that the linked answer can help. – May 29 '13 at 16:38 | |
Actually, wait() releases the mutex and yield the thread atomically so that nothing happens while the thread is being yield. – May 29 '13 at 16:41 |