c ++ Linux中的线程无限期地等待

时间:2018-05-11 20:01:27

标签: c++ linux multithreading

我们必须编写将创建两个线程的程序。第一个线程将从键盘请求信,然后它将向正在等待它的第二个线程发送信号。然后它会将这封信改为上一封,如果这封信不是'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;
}

2 个答案:

答案 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()开始等待之前发送信号,则信号将丢失。

不足: 建议:

  1. 正确初始化互斥锁和简历。
  2. 修复函数second()中的互斥范围问题;和
  3. main()中,在互斥锁的保护下执行线程创建(但不是连接);和
  4. 函数first()中的
  5. (仅)将pthread_cond_wait()移动到循环的末尾(确保适当地扩展互斥的范围),以便first()没有等待信号执行第一次迭代;和
  6. pthread_cond_signal()删除main(),因为不再需要它。
  7. 请注意,在保持目标CV的关联互斥锁被锁定的情况下执行pthread_cond_signal()是安全的。不要求这样做,但有些人建议将其作为良好做法。

答案 1 :(得分:0)

您应该初始化互斥锁变量。

除此之外,似乎第一个线程将等待事件dadam。 确保为线程first生成事件。