linux 在C中使用互斥体使用2个线程打印奇数和偶数

wswtfjt7  于 2022-11-28  发布在  Linux
关注(0)|答案(7)|浏览(201)

程序中的两个线程交替打印偶数和奇数,直到100。我试过了,它起作用了。有没有办法访问main内部共享数据的值,并在值达到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)
{
    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);
}
qhhrdooz

qhhrdooz1#

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 );
 }
}
58wvjzkj

58wvjzkj2#

有几个错误,在我之前发布的代码中,我纠正了这些错误,这个程序打印从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);
}
yiytaume

yiytaume3#

#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;
}
dsekswqp

dsekswqp4#

Prints: 
Counter value functionCount2: 0
Counter value functionCount1: 1
Counter value functionCount2: 2
Counter value functionCount1: 3
Counter value functionCount2: 4
Counter value functionCount1: 5
Counter value functionCount2: 6
Counter value functionCount1: 7
Counter value functionCount2: 8
Counter value functionCount1: 9

#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 10

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 ) {
            printf("Counter value functionCount1: %d\n",count);
            count++;
            pthread_cond_signal( &condition_var );
        } else {
            pthread_cond_wait( &condition_var, &count_mutex );
        }
        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 ) {
            printf("Counter value functionCount2: %d\n",count);
            count++;
            pthread_cond_signal( &condition_var );
        } else {
            pthread_cond_wait( &condition_var, &count_mutex );
        }
        if( count >= COUNT_DONE ) {
            pthread_mutex_unlock( &count_mutex );
            return(NULL);
        }
        pthread_mutex_unlock( &count_mutex );
    }
}
ccrfmcuu

ccrfmcuu5#

这是一个非常糟糕的线程用例。让两个线程简单地交替工作负载不会给你带来任何好处。一般的想法是允许线程在等待某些资源可用的同时做 * 其他 * 工作。
如果您的两个线程要么正在执行有用的工作,要么在等待有用的工作变得可用时什么也不做,那么最好在单个执行线程中执行这些工作。
话虽如此,你 * 可以 * 将工作量划分成线程,但你的做法是有问题的。首先,你的每个线程只处理 * 一个 * 数字,然后退出,所以你不会得到接近一百个数字的打印输出。
其次,即使它们确实循环了,每一行都像:

if(shared_data++ %2 == 0)

将 * 递增 * 共享数据,即使它不应该这样做。这将导致在输出中产生"有趣"的结果。考虑一下这样的情况:每个线程在切换到另一个线程之前都经历了循环的多次迭代。
因为它是递增的,* 而不管 * 当前值,所以您可能会看到类似这样的内容:

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

线程的伪代码要求每个线程在轮到自己之前不做任何事情来影响数据。首先是主线程,与你的线程没有太大区别:

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

但是,即使您希望以线程化的方式完成此操作,互斥也不一定是一种好的方式。(上述伪代码中的收益是减轻这一点的努力,但是我非常确定pthreads并不强制yield--它可能是一个不可移植的扩展)。
有更好的(即确定性的)方法来实现线程之间的通信,这些方法 * 知道 * 控制权必须被转移,比如条件变量。

sczxawaw

sczxawaw6#

mutex m;
condition_variable cv;
int num = 0;

void Even()
{
    while (true)
    {
        {
            unique_lock<mutex> ul(m);
            cv.wait(ul, [&]() {return num % 2 == 0; });
            cout <<"Even "<<num << endl;
            num++;
            cv.notify_one();
        }
    }
}

void Odd()
{
    while (true)
    {
        {
            unique_lock<mutex> ul(m);
            cv.wait(ul, [&]() {return num % 2 == 1; });
            cout <<"ODD "<< num << endl;
            num++;
            cv.notify_one();
        }
    }
}

int main()
{
    thread t1(Odd);
    
    thread t2(Even);

    t1.join();
    t2.join();

    return 0;
}
fcy6dtqo

fcy6dtqo7#

下面是c代码打印偶数和奇数使用两个线程,与发送信号给其他线程一旦第一个线程完成,使第二个线程备份和开始使用资源.下面的程序是工作正常!!!

output:
odd_thread: 1
Even_Thread: 2
odd_thread: 3
Even_Thread: 4
odd_thread: 5
Even_Thread: 6
odd_thread: 7
Even_Thread: 8
odd_thread: 9
Even_Thread: 10

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

int n = 1;
int max = 10;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  even = PTHREAD_COND_INITIALIZER;
pthread_cond_t  odd =  PTHREAD_COND_INITIALIZER;

void* print_odd(void *x)
{
  do
  {
    pthread_mutex_lock(&lock);
    if(n%2 != 1 )
    {
        pthread_cond_wait(&odd, &lock);
        pthread_mutex_unlock(&lock);
        pthread_cond_signal(&even);

    }
    else{
    printf("odd Thread: %d\n", n);
    n++;
    pthread_mutex_unlock(&lock);
    pthread_cond_signal(&even);
    }
    }while(n <= max);

    pthread_exit(NULL);

    }

  void* print_even(void *x)
  {
    do
    {
    pthread_mutex_lock(&lock);
    if(n%2 != 0)
    {
        pthread_cond_wait(&even, &lock);
        pthread_mutex_unlock(&lock);
        pthread_cond_signal(&odd);

    }
    else{
    printf("Even Thread: %d\n", n);
    n++;
    pthread_mutex_unlock(&lock);
    pthread_cond_signal(&odd);
    }
    }while(n <= max);

     pthread_exit(NULL);

     }

     int main()
     {
      pthread_t t1, t2;

      pthread_create(&t1, NULL, print_odd, NULL);
      pthread_create(&t2, NULL, print_even, NULL);

      pthread_join(t1, NULL);
      pthread_join(t2, NULL);

     return 0;

    }

相关问题