使用C中的互斥锁使用2个线程打印奇数和偶数

时间:2014-02-25 04:35:02

标签: linux pthreads mutex

程序中的两个线程交替打印偶数和奇数到100。 我试过这个并且有效。 有没有办法访问main中的共享数据的值,并在值达到100

时终止2个线程
#include<stdio.h>
#include<pthread.h>

pthread_t tid[2];
unsigned int shared_data = 0;
pthread_mutex_t mutex;
unsigned int rc;
//prototypes for callback functions

void* PrintEvenNos(void*);
void* PrintOddNos(void*);

void main(void)
{
    pthread_create(&tid[0],0,&PrintEvenNos,0)
    pthread_create(&tid[1],0,&PrintOddNos,0);
    sleep(3);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
}

void* PrintEvenNos(void *ptr)
{
    pthread_mutex_lock(&mutex);
    do
    {
       if(shared_data%2 == 0)
       {
         printf("Even:%d\n",shared_data);
         shared_data++;
       } else {
          rc=pthread_mutex_unlock(&mutex);//if number is odd, do not print, release mutex
       }
    } while(shared_data <= 100);
}

void* PrintOddNos(void* ptr1)
{
    rc = pthread_mutex_lock(&mutex);
    do
    {
       if(shared_data%2 != 0)
       {
          printf("odd:%d\n",shared_data);
          shared_data++;
       } else {
          rc = pthread_mutex_unlock(&mutex);//if number is even, do not print, release mutex
       }
    } while(shared_data <= 100);
}

5 个答案:

答案 0 :(得分:4)

错误很少,在我之前发布的代码中,我纠正了这些错误,这个程序打印出0到100的偶数和奇数值,我试过了。

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

pthread_t tid[2];
unsigned int shared_data = 0;
pthread_mutex_t mutex;
unsigned int rc;
//prototypes for callback functions

void* PrintEvenNos(void*);
void* PrintOddNos(void*);

void main(void)
{
    pthread_create(&tid[0],0,&PrintEvenNos,0);
    pthread_create(&tid[1],0,&PrintOddNos,0);
    sleep(3);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
}

void* PrintEvenNos(void *ptr)
{
     rc = pthread_mutex_lock(&mutex);
     do
     {
         if(shared_data%2 == 0)
         {
             printf("Even:%d\n",shared_data);
             shared_data++;
         }
         else
         {
             rc=pthread_mutex_unlock(&mutex);//if number is odd, do not print, release mutex
         }
     } while (shared_data <= 100);
}

void* PrintOddNos(void* ptr1)
{
    rc = pthread_mutex_lock(&mutex);
    do
    {
        if(shared_data%2 != 0)
        {
            printf("odd:%d\n",shared_data);
            shared_data++;
        }
        else
        {
            rc = pthread_mutex_unlock(&mutex);//if number is even, do not print, release mutex
        }
    } while (shared_data <= 100);
}

答案 1 :(得分:4)

Use condition variable to synchronize both threads and a mutex to protect count

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
void *functionCount1();
void *functionCount2();
int count = 0;
#define COUNT_DONE 200

void main()
{
 pthread_t thread1, thread2;
 pthread_create( &thread1, NULL, &functionCount1, NULL);
 pthread_create( &thread2, NULL, &functionCount2, NULL);
 pthread_join( thread1, NULL);
 pthread_join( thread2, NULL);
 exit(0);
}

// Print odd numbers
void *functionCount1()
{
  for(;;) {
   // Lock mutex and then wait for signal to relase mutex
   pthread_mutex_lock( &count_mutex );
   if ( count % 2 != 0 ) {
     pthread_cond_wait( &condition_var, &count_mutex );
   }
   count++;
   printf("Counter value functionCount1: %d\n",count);
   pthread_cond_signal( &condition_var );
   if ( count >= COUNT_DONE ) {
     pthread_mutex_unlock( &count_mutex );
     return(NULL);
   }
   pthread_mutex_unlock( &count_mutex );
 }
}

// print even numbers
void *functionCount2()
{
  for(;;) {
  // Lock mutex and then wait for signal to relase mutex
  pthread_mutex_lock( &count_mutex );
  if ( count % 2 == 0 ) {
    pthread_cond_wait( &condition_var, &count_mutex );
  }
  count++;
  printf("Counter value functionCount2: %d\n",count);
  pthread_cond_signal( &condition_var );
  if( count >= COUNT_DONE ) {
    pthread_mutex_unlock( &count_mutex );
    return(NULL);
  }
  pthread_mutex_unlock( &count_mutex );
 }
}

答案 2 :(得分:1)

#

答案 3 :(得分:0)

这是一个非常糟糕的线程用例。只需两个线程交替工作负载就不会获得任何好处。一般的想法是允许线程在等待某些资源可用时执行其他工作。

如果你的两个线程要么正在做有用的工作,要么在等待有用的工作变得可用时什么都不做,你最好在一个执行线程中做这件事。

话虽如此,你可以将工作负载划分为线程,但你完成它的方式是有问题的。首先,你的每个线程只是处理一个号码然后退出,所以你不会得到任何接近一百个数字的打印出来。

其次,即使他们做了循环,每一行都像:

if(shared_data++ %2 == 0)

增加共享数据,即使它不应该。这将导致输出中的“有趣”结果。想一想每个线程在切换到另一个线程之前经历了多次循环迭代的情况。

因为无论当前值是否增加,您可能会看到类似的内容:

0 2 4 6 7 9 11 13 14 16 18 20 21 23 ...

将运行的线程的伪代码要求每个线程 nothing 以影响数据,直到它们轮到它们为止。首先,主线程与你的主线没什么不同:

def main()
    set item to 0
    start thread evenThread
    start thread oddThread
    wait for evenThread to finish
    wait for oddThread to finish
    exit

然后是两个工作线程,结构非常相似:

def evenThread():
    grab mutex
    repeat forever:
        while item is odd:
            release mutex
            yield if possible
            grab mutex

        # item now guaranteed to be even
        print item
        increment item
        if item is 101:
            exit repeat loop
    release mutex

def oddThread():
    grab mutex
    repeat forever:
        while item is even:
            release mutex
            yield if possible
            grab mutex

        # item now guaranteed to be odd
        print item
        increment item
        if item is 100:
            exit repeat loop
    release mutex

但是,即使您希望以线程方式完成此操作,互斥锁也不一定是一种好方法。每个线程都有可能在完成此周期的工作后继续运行,从而导致工作浪费(上述伪代码中的产量是为了缓解这种情况,但我很确定yield pthreads没有规定 - 但它可能是一个非便携式扩展。)

有更好的(即确定性的)方法来影响必须传输知道控制的线程之间的通信。例如条件变量之类的东西。

答案 4 :(得分:0)

#include<stdio.h>
#include<pthread.h>
int data =0;

pthread_mutex_t lock;
pthread_cond_t cond;

void * even(void *tid)
{
    while(data < 30)
    {
        pthread_mutex_lock(&lock);
        if(data%2)
            pthread_cond_wait(&cond,&lock);
        else
        {
            printf("Tid %ld even %d\n",pthread_self(),data++);
            pthread_cond_signal(&cond);
        }
            pthread_mutex_unlock(&lock);    // should come outside else as mutex is locked above if
    }
    pthread_exit(&data);
}

void * odd()
{
    while(data < 30) 
    {   
        pthread_mutex_lock(&lock);
        if(!(data%2))
            pthread_cond_wait(&cond,&lock);
        else
        {
            printf("Tid %ld odd %d\n",pthread_self(),data++);
            pthread_cond_signal(&cond);
        }
            pthread_mutex_unlock(&lock);
    }   
    pthread_exit(&data);
}

int main()
{
    pthread_mutex_init(&lock,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_t tid[2];
    pthread_create(&tid[0],NULL,even, (void*)&tid[0]);
    pthread_create(&tid[1],NULL,odd, (void*)&tid[1]);
    void *ret[2];
    pthread_join(tid[0], &ret[0]);
    pthread_join(tid[1], &ret[1]);
    printf("return value %d \n",*(int*)ret[0]);
    printf("return value %d \n",*(int*)ret[1]);

    return 0;
}