pthead cond的理解

pthread_cond_wait/pthread_cond_timedwait返回時候需要得到mutex,因此有如下兩個問題
-對於pthread_cond_timedwait()的理解:到了timeout,下面的程序一定能執行嗎?
  答案應該是否定的,pthread_cond_timedwait()也需要獲得mutex,否則也不能喚醒
-pthread_cond_signal()只能喚醒一個,如果有多個等待,則不能喚醒
  pthread_cond_broadcast()能喚醒多個,但是通常需要等待mutex按照順序一個一個進行下面處理

因此在多線程的程序設計中要注意任何一個線程都不能長時間佔用資源

下面有幾個例子

例子1,時間到,但是timedwait不能即使返回

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>

void *fun1(void *arg);
void *fun3(void *arg);

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int a = 10;
int b = 5;

int main(void)
{
    printf("hello\n");

    pthread_t id1;
    pthread_create(&id1, NULL, fun1, NULL);
    pthread_t id3;
    pthread_create(&id3, NULL, fun3, NULL);

    pthread_join(id1, NULL);
    pthread_join(id3, NULL);
    printf("main exit\n");

    return 0;
}

void *fun1(void *arg)
{   
    printf("now in the fun1\n");
    pthread_mutex_lock(&mutex);
    printf("fun1 lock\n");
    struct timeval now;
    struct timespec timeout;
    int retcode = 0;

    while (a > b) {
        gettimeofday(&now, NULL);
        timeout.tv_sec = now.tv_sec + 1;
        timeout.tv_nsec = now.tv_usec * 1000;
        retcode = pthread_cond_timedwait(&cond, &mutex, &timeout);
        printf("---fun1 timedwait end\n");
    }
    printf("fun1 will unlock\n");
    pthread_mutex_unlock(&mutex);
    
    return NULL;
}   
void *fun3(void *arg)
{
    printf("now in the fun3\n");
    sleep(3);
    pthread_mutex_lock(&mutex);
    printf("fun3 lock\n");
    a = 3;
    pthread_cond_broadcast(&cond);
    printf("fun3 broadcast and wait 10s\n");
    sleep(10);
    printf("fun3 will unlock\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

執行結果

hello
now in the fun1
fun1 lock
now in the fun3
---fun1 timedwait end
---fun1 timedwait end
fun3 lock
fun3 broadcast and wait 10s
fun3 will unlock
---fun1 timedwait end
fun1 will unlock
main exit


例子2 cond_signal不能喚醒多個 (修改下面的註釋,可以展示另外一個問題)

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>

void *fun1(void *arg);
void *fun2(void *arg);
void *fun3(void *arg);

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int a = 10;
int b = 5;

int main(void)
{
    printf("hello\n");

    pthread_t id1;
    pthread_create(&id1, NULL, fun1, NULL);
    pthread_t id2;
    pthread_create(&id2, NULL, fun2, NULL);
    pthread_t id3;
    pthread_create(&id3, NULL, fun3, NULL);

    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
    pthread_join(id3, NULL);
    printf("main exit\n");

    return 0;
}

void *fun1(void *arg)
{
    printf("now in the fun1\n");
    pthread_mutex_lock(&mutex);
    printf("fun1 lock\n");
    while (a > b)
        pthread_cond_wait(&cond, &mutex);
    //printf("fun1 end wait\n");
    //sleep(10);
    printf("fun1 will unlock\n");
    pthread_mutex_unlock(&mutex);

    return NULL;
}
void *fun2(void *arg)
{
    printf("now in the fun2\n");
    pthread_mutex_lock(&mutex);
    printf("fun2 lock\n");
    while (a > b)
        pthread_cond_wait(&cond, &mutex);
    //printf("fun2 end wait\n");
    //sleep(10);
    printf("fun2 will unlock\n");
    pthread_mutex_unlock(&mutex);

    return NULL;
}
void *fun3(void *arg)
{
    printf("now in the fun3\n");
    sleep(3);
    pthread_mutex_lock(&mutex);
    printf("fun3 lock\n");
    a = 3;
    //pthread_cond_broadcast(&cond);
    pthread_cond_signal(&cond);
    printf("fun3 will unlock\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

結果:其中一個線程不能退出(這裏是fun2)

hello
now in the fun1
now in the fun3
now in the fun2
fun1 lock
fun2 lock
fun3 lock
fun3 will unlock
fun1 will unlock

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章