我希望你能帮助我解决问题。我的程序正在做一些我不太懂的事情。 计划目的如下: 创建两个线程(task_timer和task_read)。 这些线程必须在标准输出(stdout)上显示以下消息: “Tache 1 Tache 2 Tache 1 Tache 2 ......“
代码:
static void* task_timer(void* arg);
static void* task_read(void* p);
struct strShared{
pthread_mutex_t mut;
pthread_mutex_t mut2;
pthread_cond_t synchro;
pthread_cond_t synchro2;
};
struct strTimer{
int wt;
strShared* psh;
};
static void* task_timer(void* p){
time_t echeance;
strTimer* timer;
int time_waiting = 1000;
time_t now;
if(p != NULL){
timer = p;
time_waiting = timer->wt; //ms
echeance = time (NULL) + TIME_OF_THREAD;
while (1)
{
pthread_mutex_lock(&timer->psh->mut);
printf("Tache 1\n");
pthread_cond_signal(&timer->psh->synchro);
pthread_cond_wait(&timer->psh->synchro2, &timer->psh->mut);
pthread_mutex_unlock(&timer->psh->mut);
}
}
return NULL;
}
static void* task_read(void* p){
strTimer* timer;
if(p != NULL){
timer = p;
while(1){
pthread_mutex_lock(&timer->psh->mut);
pthread_cond_wait(&timer->psh->synchro, &timer->psh->mut);
printf("Tache 2\n");
pthread_cond_signal(&timer->psh->synchro2);
pthread_mutex_unlock(&timer->psh->mut);
}
}
return NULL;
}
int main (void)
{
pthread_t ttimer;
pthread_t tread;
/* TIMER */
strTimer timer;
strShared shtimer;
shtimer.mut = PTHREAD_MUTEX_INITIALIZER;
shtimer.mut2 = PTHREAD_MUTEX_INITIALIZER;
shtimer.synchro = PTHREAD_COND_INITIALIZER;
shtimer.synchro2 = PTHREAD_COND_INITIALIZER;
timer.psh = &shtimer;
timer.wt = 1000;
/* Threads */
pthread_create(&ttimer, NULL, task_timer, &timer);
pthread_create(&tread, NULL, task_read, &timer);
pthread_join(ttimer,NULL);
pthread_join(tread,NULL);
return 0;
}
据我所知,这段代码是实现这一目标的好方法。然而,它没有工作,我想我做了一些错误。根据我的说法,它的工作原理如下:
然而,事情并非如此。实际上,在显示“Tache 1”后程序似乎被卡住了。有人可以解释一下为什么会这样吗?我想我觉得不好但我想明白......
非常感谢, esc39
答案 0 :(得分:0)
如果您不熟悉多线程,我建议不要使用条件变量。您不需要为所描述的目标使用任何条件变量。因此,删除两个线程中的pthread_cond_wait和pthread_cond_signal行。
相反,您可以在解锁每个线程中的互斥锁后添加睡眠功能。对于例如task_read可以修改为:
pthread_mutex_lock(&timer->psh->mut);
printf("Tache 2\n");
pthread_mutex_unlock(&timer->psh->mut);
usleep(10000);
答案 1 :(得分:0)
让我们看看task_timer
首先获得锁定时会发生什么。
pthread_mutex_lock(&timer->psh->mut); /*acquires a lock*/ /*|*/
printf("Tache 1\n"); /*output*/ /*|*/
pthread_cond_signal(&timer->psh->synchro); /*sends a signal*/ /*|*/ /* no one is waiting for the signal on this cond, so the signal is ignored*/
pthread_cond_wait(&timer->psh->synchro2, &timer->psh->mut); /*releases lock and waits for signal*/ /*|*/ pthread_mutex_lock(&timer->psh->mut); /*acquires a lock*/
/*|*/ pthread_cond_wait(&timer->psh->synchro, &timer->psh->mut); /*releases lock and waits for signal*/
/*|*/
/*|*/
/*|*/
/*|*/ printf("Tache 2\n"); /*never happens*/
pthread_mutex_unlock(&timer->psh->mut); /*never happens*/ /*|*/ pthread_cond_signal(&timer->psh->synchro2);
/*|*/ pthread_mutex_unlock(&timer->psh->mut);
死锁。
简单配方:将pthread_cond_signal()
个电话放在关键部分之外。考虑到这是一个经验法则。当你有几个或多个线程与同一组mutex
/ cond
同步时,我很难想象一个从关键部分发出信号是合理的情况。信号和广播的语义就像:嘿,伙计们,我完成了关于关键资源的工作,你可以直接关注。当线程在临界区内时,通过发信号通知cond
它会产生错误的声明。因为没有完成。
pthread_cond_wait()
。
因此,每个线程的基本算法都是(伪代码):
while(loop_again) {
do_processing_on_non_critical_resources(); /* it's optional */
lock(mutex);
while(not_my_turn) { /* explained later */
wait(cond,mutex);
}
do_processsing_on_critical_resources();
set_flag_to_other_thread();
unlock(mutex);
signal(cond);
do_processing_on_non_critical_resources(); /* it's optional */
}
对not_my_turn
的检查是while
循环而非简单if
检查,因为根据文档,可能会出现虚假唤醒
pthread_cond_timedwait()
或pthread_cond_wait()
:
使用条件变量时,总会有一个布尔谓词,涉及与每个条件等待关联的共享变量,如果线程应该继续,则为true。可能会发生
pthread_cond_timedwait()
或pthread_cond_wait()
函数的虚假唤醒。由于pthread_cond_timedwait()
或pthread_cond_wait()
的返回并不意味着该谓词的值,因此应在返回时重新评估谓词。
所以,上面你有一个同步线程的一般情况。但是对于您的情况,answer from M.KHd是正确且充足的。