pthread_cond_timedwait的教训

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012266559/article/details/82756325

写给自己看的

说明:

根据代码总结 pthread_cond_timedwait 只有在先获得锁的情况下才能使用,未获得锁的情况下使用将导致不能获得锁。

  1. 由于条件会被wait线程读取,被signal/broadcast线程修改,即写入。为了防止出现竞争,需要和mutex一起使用,使用mutex来保护条件。
  2. 在mutex已经锁住的情况下,才能调用wait。
  3. 由于spurious wakeup(虚假唤醒)的原因,wait函数返回并不代表条件已经成立,在wait函数返回后,需要再次判断条件是否成立。因此需要将wai调用放到while循环中。

这是最初的函数:

(其实应该用个共享变量,作为条件,而不是只用mutex,cond)

void *thread0(void* arg){
    int i = pthread_self(), ret = 0;
    pthread_cleanup_push(&cleanup, &i);
    int loop = 0;
    cout<<"thread0 start"<<endl;
    while (ret = pthread_mutex_trylock(&mutex)){
        loop++;
        cout<<"thread0 timespawn "<<loop*3<< " "<<strerror(ret)<<endl;
        struct timeval now;
        struct timespec outtime;
        gettimeofday(&now, NULL);
        outtime.tv_sec = now.tv_sec + 5;
        outtime.tv_nsec = now.tv_usec * 1000;
        //--------------------- 问题发生在这,看着很正常 ----------------------------------
        cout<<"thread0 timedwait "<<strerror(pthread_cond_timedwait(&cond, &mutex, &outtime))<<endl;
    }
    cout<<"thread0 end"<<endl;
    pthread_mutex_unlock(&mutex);
    pthread_cleanup_pop(1);
    return NULL;
}

最后的代码:

其实改了之后完全没用用到条件变量。只不过我懒得删。

#include "pthread.h"
#include "sys/time.h"
#include "errno.h"
#include "string.h"
#include "unistd.h"
#include "iostream"

using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void cleanup(void* arg){
    int i = *(int*)arg;
    cout<<"thread "<<i<<" call cleanup"<<endl;
    pthread_mutex_unlock(&mutex);
    pthread_cond_broadcast(&cond);
}

void *thread0(void* arg){
    int i = pthread_self(), ret = 0;
    pthread_cleanup_push(&cleanup, &i);
    int loop = 0;
    cout<<"thread0 start"<<endl;
    while (ret = pthread_mutex_trylock(&mutex)){
        loop++;
        cout<<"thread0 timespawn "<<loop*3<< " "<<strerror(ret)<<endl;
        sleep(3);
    }
    cout<<"thread0 end"<<endl;
    pthread_mutex_unlock(&mutex);
    pthread_cleanup_pop(1);
    return NULL;
}

void *thread(void* arg){
    int i = pthread_self();
    pthread_cleanup_push(&cleanup, &i);
    pthread_mutex_lock(&mutex);
    cout<<"thread start"<<endl;
    sleep(3);
    cout<<"thread end"<<endl;
    cout<<"thread unlock "<<pthread_mutex_unlock(&mutex)<<endl;
    cout<<"thread broad "<<pthread_cond_broadcast(&cond)<<endl;
    pthread_cleanup_pop(1);
    return NULL;
}

int main(){
    pthread_t tid[2];
    cout<<"main create"<<endl;
    pthread_create(&tid[0], NULL, thread, NULL);
    sleep(1);
    pthread_create(&tid[1], NULL, thread0, NULL);

    cout<<"main end"<<endl;
    pthread_join(tid[0], NULL);    
    pthread_join(tid[1], NULL);    
    cout<<"main exit"<<endl;
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u012266559/article/details/82756325