使用线程打印奇数和偶数

时间:2014-11-30 17:55:47

标签: c multithreading pthreads

我知道我的问题有很多例子。但是,我想理解为什么我编写的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;
    }
}

非常感谢。

3 个答案:

答案 0 :(得分:2)

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

  1. even()获取锁定
  2. even()打印count(即0)并发出条件信号(虽然odd()无法唤醒,直到even()释放锁定
  3. even()count增加到1
  4. even()释放锁定,并odd()唤醒。
  5. odd()count增加到2
  6. odd()释放锁定(但尚未发出信号)
  7. odd()获取锁定
  8. odd()等待,因为count是偶数(== 2)...现在两个线程都在等待,并且两者都不能发出信号。
  9. 根据首先使用哪个线程,事情可能会略有不同,但两个线程仍然会以类似于上述的方式陷入困境。

    这两个例子都不可靠,因为他们在等待条件时不会考​​虑虚假的唤醒。通常情况下,如果未满足所需的唤醒条件,则应使用循环重试等待,保持锁定的全部时间,以便不会错过信号:

            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);
    

答案 1 :(得分:0)

在第一个示例中,在even()中,如果count为奇数,则pthread_cond_signal odd()如果count为偶数则运行count odd()even()将递增,并且互斥量会下降。此时even()可能会在pthread_cond_wait()到达odd()之前运行并发出even()信号。现在count永远不会再发出even()信号(因为pthread_cond_wait()现在是偶数),count' s {{1}}永远不会退出。

但是你的两个例子都是错误的。您是(上一个完整行)在保护它的互斥锁之外读取{{1}}。

答案 2 :(得分:-1)

#include <stdio.h>
#include <pthread.h>
#include<iostream>
void *odd(void* data);
void *even(void* data);
static int count=0;
pthread_mutex_t mutex;
pthread_cond_t cond;
int main()
{

   pthread_t thread1,thread2;

   pthread_create(&thread1,NULL,&even,0);

   pthread_create(&thread2,NULL,&odd,0);

   pthread_join(thread1,NULL);
   pthread_join(thread2,NULL);

   return 0;
}




void *even(void* data)
{

   pthread_mutex_lock(&mutex);
   while(count< 10)
   {
      while(count%2!=0)
      {
         pthread_cond_wait(&cond,&mutex);
      }

      std::cout<<count;
      count++;
      pthread_mutex_unlock(&mutex);
      pthread_cond_signal(&cond);
   }
   pthread_exit(0);
}

void *odd(void* data)
{
   pthread_mutex_lock(&mutex);
   while(count<10)
   {
      while(count%2!=1)
      {
         pthread_cond_wait(&cond,&mutex);
      }

      std::cout<<count;
      count++;
      pthread_mutex_unlock(&mutex);
      pthread_cond_signal(&cond);
   }
   pthread_exit(0);
}