zoukankan      html  css  js  c++  java
  • Why does pthread_cond_signal not work?【转】

    转自:http://stackoverflow.com/questions/16819169/why-does-pthread-cond-signal-not-work#

    0 down vote favorite

     

    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.
    ", 0, counter);
    
        return 0;
    }
    
    void * worker_one() {
        printf("Worker one started.
    ");
    
        pthread_mutex_lock(&mutex);
    
        printf("Worker one starting work.
    ");
        while (counter < 10000) {
            counter += 7;
        }
    
        pthread_cond_signal(&cond_a);
    
        printf("Worker one finished work with: %d.
    ", counter);
    
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
    }
    
    void * worker_two() {
        printf("Worker two started.
    ");
    
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond_a, &mutex);
    
        printf("Worker two starting work.
    ");
        while (counter > 1000)
            counter -= 3;
    
        printf("Worker two finished work with: %d.
    ", counter);
    
        pthread_cond_signal(&cond_b);
        pthread_mutex_unlock(&mutex);
    
        sleep(1);
    
        pthread_exit(NULL);
    }
    
    void * worker_three() {
        printf("Worker three started.
    ");
    
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond_b, &mutex);
    
        printf("Worker three starting work.
    ");
    
        counter /= 2;
    
        printf("Worker three finished work with: %d.
    ", 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? – bodokaiser 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. – user7116 May 29 '13 at 16:25
        
    ok did not knew anything about this – bodokaiser May 29 '13 at 16:25

    6 down vote accepted

     

    I have answered a similar question here: pthread condition variables on Linux, odd behaviour.

    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); 
    Is the testing case a simple external flag or something pthread internal? I use the example from computing.llnl.gov/tutorials/pthreads but there are no flags actually – bodokaiser May 29 '13 at 16:33
     
     
    @bodokaiser: you'll have to make up a variable, but a simple boolean flag will do. Spurious wakeups are a reality unfortunately. – user7116 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? – bodokaiser 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. – Ben 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. – Ben May 29 '13 at 16:41
  • 相关阅读:
    《PS技巧精华全部在这里!》
    c#的dictionary为什么在扩容时会以素数扩容
    初识Lua
    常用的排序
    像gal一样讲故事~
    打枪的实现
    武器的方向,人物和武器的翻转
    虚拟摇杆的修改
    实现虚拟摇杆的移动
    itemPool和MessageCenter
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/6072858.html
Copyright © 2011-2022 走看看