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

问题描述 投票:0回答:8

程序中的两个线程交替打印偶数和奇数,直到 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);
}
linux pthreads mutex
8个回答
6
投票
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 );
 }
}

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

4
投票
#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;
}

3
投票
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 );
    }
}

0
投票

这是一个非常糟糕的线程用例。让两个线程简单地交替工作负载不会给你带来任何好处。总体思路是允许线程在等待某些资源可用时执行其他工作。

如果您的两个线程要么正在执行有用的工作,要么在等待有用的工作可用时完全不执行任何操作,那么您最好在单个执行线程中执行此操作。

话虽如此,您可以将工作负载划分为多个线程,但您这样做的方式是有问题的。首先,每个线程只处理一个数字然后退出,因此您不会打印出近一百个数字。

其次,即使它们确实循环,每一行都像:

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

但是,即使您希望以线程方式完成此操作,互斥体也不一定是一个好方法。每个线程有可能在完成本周期的工作后继续运行,从而导致工作浪费(上面伪代码中的yield是为了缓解这种情况,但我很确定
yield

不是)由 pthreads 强制要求 - 但它可能是一个不可移植的扩展)。


有更好的(即确定性的)方法来实现线程之间的通信,这些线程知道必须转移控制权。例如,诸如条件变量之类的东西。

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


0
投票
我想到使用静态变量来共享数据和最大限制。

0
投票

代码:

#include<stdio.h> #include<pthread.h> pthread_mutex_t pmLock; static int shared = 0; static int limit = 10; void* printEven(){ printf("This is printEven() start.\n"); pthread_mutex_lock(&pmLock); while(shared <= limit){ if(shared%2 == 0){ printf("Even:%d\n",shared); shared++; } pthread_mutex_unlock(&pmLock); } printf("This is printEven() End.\n"); } void* printOdd(){ printf("This is printOdd() start.\n"); pthread_mutex_lock(&pmLock); while(shared <= limit){ if(shared%2 != 0){ printf("Odd:%d\n",shared); shared++; } pthread_mutex_unlock(&pmLock); } printf("This is printOdd() End.\n"); } int main(){ //init mutex lock. if (pthread_mutex_init(&pmLock, NULL) != 0) { printf("\n mutex init has failed\n"); return 1; } pthread_t thread_ids[2]; printf("Before Thread\n"); pthread_create(&thread_ids[0], NULL, printEven, NULL); pthread_create(&thread_ids[1], NULL, printOdd, NULL); pthread_join(thread_ids[0], NULL); pthread_join(thread_ids[1], NULL); printf("After Thread\n"); // destroy mutex pthread_mutex_destroy(&pmLock); return 0; }

下面是使用两个线程打印偶数和奇数的c代码,一旦第一个线程完成,就向其他线程发送信号,以便第二个线程备份并开始使用资源。
下面的程序运行良好!!!

-1
投票

© www.soinside.com 2019 - 2024. All rights reserved.