我知道我的问题有很多例子。但是,我想了解为什么我编写的1个程序行不通,而其他程序却不行。

这是我写的。

void * even()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        if(count % 2 == 0)
        {
            printf("count %d\n",count);
            pthread_cond_signal(&cond);
        }
        else
        {
            pthread_cond_wait(&cond,&lock);
        }
            count++;
        pthread_mutex_unlock(&lock);

        if(count >= 100) return NULL;
    }
}


void * odd()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        if(count % 2 == 1)
        {
            printf("count %d\n",count);
            pthread_cond_signal(&cond);
        }
        else
        {
            pthread_cond_wait(&cond,&lock);
        }
            count++;
        pthread_mutex_unlock(&lock);

        if(count >= 100) return NULL;
    }
}

因此,上面的代码有时仅输出0或0和1。但是下面的代码工作正常。
void * even()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        if(count % 2 == 0)
        {
            printf("count %d\n",count);
            count++;
            pthread_cond_signal(&cond);
        }
        else
        {
            pthread_cond_wait(&cond,&lock);
        }
        pthread_mutex_unlock(&lock);

        if(count >= 100) return NULL;
    }
}


void * odd()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        if(count % 2 == 1)
        {
            printf("count %d\n",count);
            count++;
            pthread_cond_signal(&cond);
        }
        else
        {
            pthread_cond_wait(&cond,&lock);
        }
        pthread_mutex_unlock(&lock);

        if(count >= 100) return NULL;
    }
}

非常感谢。

最佳答案

在第一个示例中,可能会发生以下变化:

  • even()获取锁
  • even()显示count(为0)并发出条件信号(尽管odd()even()释放锁定之前无法唤醒)
  • even()count递增为1
  • even()释放锁定,并且odd()唤醒。
  • odd()count递增为2
  • odd()释放锁定(但尚未发出信号)
  • odd()获取锁
  • odd()等待,因为count是偶数(== 2)...现在,两个线程都在等待,并且两个线程都无法发出信号。

  • 根据哪个线程先发生,事情可能会略有不同,但是两个线程仍然会以与上述类似的方式卡住。

    不过,这两个示例都不可靠,因为它们在等待条件时并未考虑到虚假唤醒。通常,如果不满足所需的唤醒条件,则应使用循环重试等待,并始终保持锁定状态,这样就不会丢失信号:
            pthread_mutex_lock(&lock);
            /* ...stuff... */
                /* Use a loop to restart the wait if it was interrupted early */
                while(count % 2 != 0)
                    pthread_cond_wait(&cond,&lock);
            /* ...stuff... */
            pthread_mutex_unlock(&lock);
    

    10-08 12:55