C 使用pthreads的条件等待

C 使用pthreads的条件等待,c,pthreads,race-condition,C,Pthreads,Race Condition,我似乎遇到了一个可能的死锁,有一个pthreads条件变量 这是密码 thread function(){ for (condition){ do work /* should the thread continue? */ if (exit == 1){ break; /* exit for */ } } /* end for */ pthread_mutex_lock(&mt

我似乎遇到了一个可能的死锁,有一个pthreads条件变量

这是密码

thread function(){
    for (condition){
        do work
        /* should the thread continue? */
        if (exit == 1){
            break; /* exit for */
        } 
     } /* end for */

pthread_mutex_lock(&mtxExit);
exit = 0;
pthread_cond_signal(&condVar);
pthread_mutex_unlock(&mtxExit);
}
主要功能如下:

function main(){
    if (thread is still active){
          pthread_mutex_lock(&mtxExit);
          exit = 1;
          pthread_mutex_unlock(&mtxExit);
          } /* end if */
    while (exit == 1){
       pthread_mutex_lock(&mtxExit);
       /* check again */
       if (exit == 1)
           pthread_cond_wait(&condVar, &mtxExit);
       pthread_mutex_unlock(&mtxExit);
       }
    create new thread()
    ....
    }
代码总是卡在cond_wait.:(

编辑:

让我在帖子中添加一些说明来解释我在做什么

在任何给定的时间,我只需要运行一个线程。我有一个函数启动线程,告诉它做什么,主线程继续它的工作

下次主线程决定需要生成另一个线程时,它必须确保先前启动的线程已退出。我不能让两个线程同时处于活动状态,因为它们会相互干扰。这是根据设计和我正在处理的问题的定义

这就是我遇到问题的地方

这是我的方法:

启动线程,让它完成它的工作

线程在其作业的每个步骤中都会检查它是否仍然相关。这就是“退出”出现在图片中的地方。如果需要告诉线程它不再相关,则主线程将“退出”设置为1

在大多数情况下,线程将在主线程决定生成另一个线程之前退出。但我仍然需要考虑到,当主线程准备启动另一个线程时,线程仍然处于活动状态

因此,主线程设置“exit”的值,并需要等待线程退出。我不想使用带有0的pthread_kill作为信号,因为这样主线程将处于循环中,浪费CPU周期。我需要主线程放弃控制并休眠/等待线程退出

因为我一次只需要一个线程,所以我不需要担心扩展到更多线程。解决方案将永远不会有多个线程。我只需要一个可靠的机制来测试我的线程是否仍处于活动状态,如果仍然处于活动状态,则发出退出信号,等待它退出并启动下一个线程

从我的测试来看,似乎主线程仍然在输入条件变量,即使线程可能已经退出,或者信号根本没有传递到主线程。它永远在那里等待。在某些情况下,在调试器中,我看到exit的值设置为0,主线程仍然在等待信号.在某些地方似乎有比赛条件

我不喜欢我现在如何设置代码,它太混乱了。现在它只是一个概念证明,我很快就会转向更好的解决方案。我的挑战是可靠地通知线程退出,等待它退出


非常感谢您的时间。

您是否忘记初始化条件变量

pthread_cond_init(&condVar, NULL)
while(exit==1){

在您引用的代码中,您引用的方式我看不出任何特殊问题。它不干净,但似乎功能正常。是什么让我相信您正在其他地方将
exit
设置为0,而没有发出信号。或者线程在某个地方卡住了

但是考虑到那些提示您试图在启动另一个线程之前向一个线程发送终止信号的注释,我认为您做得不对。通常,如果一个信号没有丢失,就不应该依赖pthread condition信令。尽管状态变量
exit
似乎涵盖了这一点,但它仍然是错误的应用程序pthread条件的定义

在这种情况下,您可以尝试使用信号量。终止时,线程会增加终止信号量,以便main可以等待(减少)信号量

thread function()
{
   for (condition)
   {
      do work
      /* should the thread continue? */
      if (exit == 1) {
         break; /* exit for */
      } 
   } /* end for */
   sem_post(&termSema);
}

function main()
{
    if (thread is still active)
    {
          exit = 1;
          sem_wait(&termSema);
          exit = 0;
    }
    create new thread()
    ....
}

一般来说,我建议寻找一些线程池实现。因为使用状态变量来同步线程仍然是错误的,并且不能扩展到多个线程。而且容易出错。

当代码卡在
pthread\u cond\u wait
中时,是
退出
1还是0?如果
退出
1,应该被卡住

如果
退出
0,则最有可能出现以下两种情况之一:

1) 某些代码将退出设置为0,但没有向条件变量发送信号


2) 一些线程阻塞在
pthread\u cond\u wait上,消耗了一个信号,但没有执行您需要执行的任何操作。

您当前的实现存在各种各样的计时问题(因此出现了问题)

要确保线程已完成(并且其资源已释放),应调用
pthread\u join()

这里不需要
pthread\u cond\t

使用
pthread\u cancel()
通知线程不再需要它,而不是像您当前所做的那样使用一个标志,这可能更有意义

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_func(void *arg) {
    int i;

    for (i = 0; i < 10; i++) {
        /* protect any regions that must not be cancelled... */
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

        /* very important work */
        printf("%d\n", i);

        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

        /* force a check to see if we're finished */
        pthread_testcancel();

        /* sleep (for clarity in the example) */
        sleep(1);
    }

    return NULL;
}

void main(void) {
    int ret;
    pthread_t tid;

    ret = pthread_create(&tid, NULL, thread_func, NULL);
    if (ret != 0) {
        printf("pthread_create() failed %d\n", ret);
        exit(1);
    }

    sleep(5);

    ret = pthread_cancel(tid);
    if (ret != 0) {
        printf("pthread_cancel() failed %d\n", ret);
        exit(1);
    }

    ret = pthread_join(tid, NULL);
    if (ret != 0) {
        printf("pthread_join() failed %d\n", ret);
        exit(1);
    }

    printf("finished...\n");
}
#包括
#包括
#包括
void*thread_func(void*arg){
int i;
对于(i=0;i<10;i++){
/*保护任何不能取消的区域*/
pthread_setcancelstate(pthread_CANCEL_DISABLE,NULL);
/*非常重要的工作*/
printf(“%d\n”,i);
pthread_setcancelstate(pthread_CANCEL_ENABLE,NULL);
/*强制检查看我们是否完成了*/
pthread_testcancel();
/*睡眠(为了在示例中清晰起见)*/
睡眠(1);
}
返回NULL;
}
真空总管(真空){
int ret;
pthread_t tid;
ret=pthread\u create(&tid,NULL,thread\u func,NULL);
如果(ret!=0){
printf(“pthread_create()失败%d\n”,ret);
出口(1);
}
睡眠(5);
ret=pthread_cancel(tid);
如果(ret!=0){
printf(“pthread_cancel()失败%d\n”,ret);
出口(1);
}
ret=pthread_join(tid,NULL);
如果(ret!=0){
printf(“pthread_join()失败%d\n”,ret);
出口(1);
}
printf(“完成…\n”);
}

同样值得注意的是:

  • exit()
  • 取决于你