pthread_cond_timedwait的教训

写给自己看的

说明:

根据代码总结 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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值