写给自己看的
说明:
根据代码总结 pthread_cond_timedwait 只有在先获得锁的情况下才能使用,未获得锁的情况下使用将导致不能获得锁。
- 由于条件会被wait线程读取,被signal/broadcast线程修改,即写入。为了防止出现竞争,需要和mutex一起使用,使用mutex来保护条件。
- 在mutex已经锁住的情况下,才能调用wait。
- 由于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;
}