我们必须编写将创建两个线程的程序。第一个线程将从键盘请求信,然后它将向正在等待它的第二个线程发送信号。然后它会将这封信改为上一封,如果这封信不是'E',它会向另一封信号发送另一封信号。什么会再次运行线程,直到你输入的字母不是'e'。
两个线程之间的通信有点类似于打乒乓球,或者至少它应该是。
下面我要添加我写的代码片段。它没有完成,但有一个问题,我无法修复或找到解决方案。当我尝试运行此代码时,它会卡住。看起来两个线程都在等待信号,所以没有任何事情发生。
有什么问题?
#include <iostream>
#include <fstream>
#include <string>
#include <pthread.h>
#include <stdlib.h>
using namespace std;
pthread_mutex_t mut;
pthread_cond_t dadam;
pthread_cond_t dudum;
char x;
void *first(void *arg) {
while(1) {
pthread_mutex_lock(&mut);
pthread_cond_wait(&dadam, &mut);
cout << "Type a letter\n";
cin >> x;
pthread_mutex_unlock(&mut);
pthread_cond_signal(&dudum);
}
}
void *second(void *arg) {
while(1) {
pthread_cond_wait(&dudum, &mut);
pthread_mutex_lock(&mut);
char y;
y = toupper(x);
cout << y << endl;
pthread_mutex_unlock(&mut);
pthread_cond_signal(&dadam);
}
}
int main()
{
pthread_t nun;
pthread_t nuno;
pthread_create(&nun, NULL, &first,NULL);
pthread_create(&nuno, NULL, &second,NULL);
pthread_cond_signal(&dadam);
pthread_join(nun, NULL);
pthread_join(nuno, NULL);
return 0;
}
答案 0 :(得分:0)
您没有初始化互斥锁或条件变量。它们具有静态持续时间,因此参与默认初始化,但不能保证它会产生可用状态。实现这一目标的通用方法是使用pthread_cond_init()
和pthread_mutex_init()
,但如果默认值足够,那么您还可以使用初始化宏:
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t dadam = PTHREAD_COND_INITIALIZER;
pthread_cond_t dudum = PTHREAD_COND_INITIALIZER;
您还尝试在不保留指定互斥锁的情况下等待CV dudum
。调用pthread_cond_wait()
时需要持有互斥锁:
pthread_mutex_lock(&mut);
pthread_cond_wait(&dudum, &mut);
(不是相反)。
但主要问题似乎是实施中的竞争条件。
在其循环的每次迭代中,函数first()
在继续之前等待CV dadam
,并且在其循环的每次迭代中,函数second()
等待在继续之前CV dudum
。如果您可以将其启动,这可能会有效,但是当您第一次启动这两个函数时,任何人都无法继续等待以发出另一个正在等待的CV的信号。您从主线程发出dadam
信号,但如果主线程在first()
开始等待之前发送信号,则信号将丢失。
不足:
建议:
second()
中的互斥范围问题;和main()
中,在互斥锁的保护下执行线程创建(但不是连接);和first()
中的pthread_cond_wait()
移动到循环的末尾(确保适当地扩展互斥的范围),以便first()
没有等待信号执行第一次迭代;和pthread_cond_signal()
删除main()
,因为不再需要它。
请注意,在保持目标CV的关联互斥锁被锁定的情况下执行pthread_cond_signal()
是安全的。不要求这样做,但有些人建议将其作为良好做法。
答案 1 :(得分:0)
您应该初始化互斥锁变量。
除此之外,似乎第一个线程将等待事件dadam
。
确保为线程first
生成事件。