简体   繁体   English

C线程打印数字序列:偶数和奇数打印线程并行运行

[英]C Threads to print sequence of numbers : with even and odd number printing threads running parallely

I am new to multithread programming. 我是多线程编程的新手。 I tried to print sequence of numbers using even and odd number printing threads, running in parallel. 我尝试使用偶数和奇数打印线程打印数字序列,并行运行。 When executed, the code enters a deadlock. 执行时,代码进入死锁状态。 Can anyone help me to solve this. 任何人都可以帮我解决这个问题。

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t even, odd;

void printfun1(void *pnt);
void printfun2(void *pnt);

main()
{

    pthread_t pthread1, pthread2;
    int ret1, ret2;
    char *message = "thread 1";
    char *message2 = "thread 2";

    ret1 = pthread_create(&pthread1, NULL, printfun1, (void *)message);

    if(ret1)
    {
        printf("thread creation failed");
    }
    ret2 = pthread_create(&pthread2, NULL, printfun2,(void*) message2);
    if(ret2)
    {
        printf("thread creation failed");
    }

    pthread_join(pthread1, NULL);
    pthread_join(pthread2, NULL);

    exit(0);
}
void printfun1(void *ptr)
{

    char* message = ptr;
    int counter = -1;

    while(counter < 50)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&even, &mutex);
        counter += 2;

        printf("%d \n", counter);
        pthread_cond_signal(&odd);
        pthread_mutex_unlock(&mutex);

        usleep( 1000000);
    }
}

void printfun2(void *ptr)
{

    char* message = ptr;
    int counter2 = 0;
    pthread_cond_signal(&even);
    while(counter2 < 50)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&odd, &mutex);
        counter2 += 2;

        printf("%d \n", counter2);
        pthread_cond_signal(&even);
        pthread_mutex_unlock(&mutex);
        usleep( 1000000);
    }
}

There are at least a couple things wrong with the program: 该计划至少有一些问题:

  1. You never initialize the condition variables: 您永远不会初始化条件变量:

     pthread_cond_init(&even, NULL); pthread_cond_init(&odd, NULL); 
  2. You can reach a deadlock if you signal a condition when the other thread isn't waiting on that condition. 如果在另一个线程没有等待该条件时发出信号,则可以达到死锁。 Normally, when you use pthread_cond_wait() , you also are checking some other shared variable in a while loop. 通常,当您使用pthread_cond_wait() ,您还在while循环中检查其他一些共享变量。 I rewrote your program to demonstrate this: 我重写了你的程序来演示这个:

     #include <stdio.h> #include <pthread.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t even = PTHREAD_COND_INITIALIZER; pthread_cond_t odd = PTHREAD_COND_INITIALIZER; void *printfun1(void *pnt); void *printfun2(void *pnt); int main(void) { pthread_t pthread1, pthread2; int ret1, ret2; ret1 = pthread_create(&pthread1, NULL, printfun1, NULL); if(ret1) { printf("thread creation failed"); } ret2 = pthread_create(&pthread2, NULL, printfun2, NULL); if(ret2) { printf("thread creation failed"); } pthread_join(pthread1, NULL); pthread_join(pthread2, NULL); } int counter = 0; void *printfun1(void *ptr) { while(counter < 50) { pthread_mutex_lock(&mutex); while ((counter & 1) == 1) pthread_cond_wait(&even, &mutex); printf("%d \\n", counter); counter++; pthread_cond_signal(&odd); pthread_mutex_unlock(&mutex); usleep( 1000000); } return NULL; } void *printfun2(void *ptr) { while(counter < 50) { pthread_mutex_lock(&mutex); while ((counter & 1) == 0) pthread_cond_wait(&odd, &mutex); printf("%d \\n", counter); counter++; pthread_cond_signal(&even); pthread_mutex_unlock(&mutex); usleep( 1000000); } return NULL; } 

    Now you can see how deadlock is avoided. 现在您可以看到如何避免死锁。 A thread only starts waiting on a condition when it knows that it needs to wait on the condition. 线程只有在知道需要等待条件时才开始等待条件。 So even if the second thread signalled the condition when the first thread wasn't waiting on it, it doesn't matter. 因此,即使第二个线程在第一个线程没有等待时发出信号,也无关紧要。

I think that to do the job right, you need three mutexes and three condition variables. 我认为要做好工作,你需要三个互斥锁和三个条件变量。 The odd thread must keep the odd mutex locked for the entire duration of the program. 奇数线程必须在程序的整个持续时间内保持奇数互斥锁的锁定。 The only time the odd mutex is unlocked is when the odd thread is waiting on its condition. 奇数互斥锁解锁的唯一时间是奇数线程在其状态下等待。 Likewise, the even thread needs to keep the even mutex locked for the duration. 同样,偶数线程需要在持续时间内保持偶数互斥锁。

And you need a main mutex and a main condition variable, so that the odd and even threads can signal main after locking their respective mutexes. 并且您需要一个主互斥量和一个主要条件变量,以便奇数和偶数线程可以在锁定其各自的互斥锁后发出主信号。

After the odd and even threads 经过奇数和偶数线程
- are up and running - 正在运行
- have locked their mutexes - 锁定了他们的互斥锁
- and are waiting on their condition variables (which unlocks the mutex) - 并等待他们的条件变量(解锁互斥锁)
then main can signal the odd thread one time to get things started. 然后main可以通过一次奇数线程来发出信号。

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

pthread_mutex_t mainMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t oddMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t evenMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mainCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t oddCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t evenCond = PTHREAD_COND_INITIALIZER;

void *printOdd( void *arg )
{
    pthread_mutex_lock( &oddMutex );        // grab the odd mutex

    pthread_mutex_lock( &mainMutex );       // signal main that the odd thread
    pthread_cond_signal( &mainCond );       // is locked and ready for action
    pthread_mutex_unlock( &mainMutex );

    for ( int counter = 1; counter < 50; counter += 2 )
    {
        pthread_cond_wait( &oddCond, &oddMutex );   // wait for the odd signal
        printf( "%d\n", counter );

        pthread_mutex_lock( &evenMutex );   // signal the even thread
        pthread_cond_signal( &evenCond );
        pthread_mutex_unlock( &evenMutex );

        usleep( 100000 );
    }

    pthread_mutex_unlock( &oddMutex );
    return NULL;
}

void *printEven( void *arg )
{
    pthread_mutex_lock( &evenMutex );       // grab the even mutex

    pthread_mutex_lock( &mainMutex );       // signal main that the even thread
    pthread_cond_signal( &mainCond );       // is locked and ready for action
    pthread_mutex_unlock( &mainMutex );

    for ( int counter = 2; counter < 50; counter += 2 )
    {
        pthread_cond_wait( &evenCond, &evenMutex ); // wait for the even signal
        printf( "%d\n", counter );

        pthread_mutex_lock( &oddMutex );    // signal the odd thread
        pthread_cond_signal( &oddCond );
        pthread_mutex_unlock( &oddMutex );

        usleep( 100000 );
    }

    pthread_mutex_unlock( &evenMutex );
    return NULL;
}

int main( void )
{
    pthread_t id1, id2;

    pthread_mutex_lock( &mainMutex );                           // grab the main mutex

    if ( pthread_create( &id1, NULL, printOdd, NULL ) != 0 )    // create the odd thread
        exit( 1 );
    pthread_cond_wait( &mainCond, &mainMutex ); // wait for the signal from the odd thread

    if ( pthread_create( &id2, NULL, printEven, NULL ) != 0 )   // create the even thread
        exit( 1 );
    pthread_cond_wait( &mainCond, &mainMutex ); // wait for the signal from the even thread

    pthread_mutex_unlock( &mainMutex );     // startup has completed, release the main mutex

    pthread_mutex_lock( &oddMutex );        // signal the odd thread to get things rolling
    pthread_cond_signal( &oddCond );
    pthread_mutex_unlock( &oddMutex );

    pthread_join( id1, NULL );              // wait for the threads to finish
    pthread_join( id2, NULL );

    exit( 0 );
}

First thing is condition variable is not initialized to "PTHREAD_COND_INTIALIAZER". 首先,条件变量未初始化为“PTHREAD_COND_INTIALIAZER”。 Coming to the program, in the first thread, i think pthread_mutex_unlock should come before pthread_cond_signal 来到程序,在第一个线程中,我认为pthread_mutex_unlock应该在pthread_cond_signal之前出现

the following code --removes the unneeded system function calls --properly handles the mutex creation/locking/unlocking/destruction --prints even/odd values from 0 through 49 --properly handles logging of errors --corrects the compiler warning about undefined function exit() --stops threads getting locked in the inner while loop --properly defines the top thread functions as 'void*' rather than 'void' --properly sets parameters to pthread_create() --properly exits the threads via pthread_exit() --and several other minor fixes 以下代码 - 删除不需要的系统函数调用 - 正确处理互斥锁创建/锁定/解锁/销毁 - 从0到49编制偶数/奇数值 - 正确处理错误记录 - 修正编译器关于undefined的警告function exit() - 停止线程在内部while循环中被锁定 - 正确地将顶层线程函数定义为'void *'而不是'void' - 正确地将参数设置为pthread_create() - 通过pthread_exit正确地退出线程() - 以及其他一些小修正

#include <stdio.h>
#include <stdlib.h>  // exit(), EXIT_FAILURE
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


void *printfun1(void *);
void *printfun2(void *);

main()
{

    pthread_t pthread1, pthread2;
    int ret1, ret2;

    ret1 = pthread_create(&pthread1, NULL, &printfun1, (void *)message);

    if(ret1)
    {
        perror("thread 1 creation failed");
        exit( EXIT_FAILURE );
    }

    ret2 = pthread_create(&pthread2, NULL, &printfun2,(void*) message2);

    if(ret2)
    {
        perror("thread 2 creation failed");
        exit( EXIT_FAILURE );
    }

    pthread_join(pthread1, NULL);
    pthread_join(pthread2, NULL);
    pthread_mutex_destroy(&mutex);

    return 0;
} // end function: main



int counter = 0;

// Note:
//     1) 0 is even so should be printed
//     2) 50 is beyond the range, so should not be printed
//     3) use do{...}while so program will exit when done, 
//        rather than getting locked in wait loop
void *printfun1(void *ptr)
{
    do
    {
        while( (counter & 1) == 0 )
        {   
            usleep(100);
        }

        pthread_mutex_lock(&mutex);
        printf("%d \n", counter);
        counter++;
        pthread_mutex_unlock(&mutex);

    } while( counter < 50 );
    pthread_exit( 0 );
} // end function: printfun1



void *printfun2(void *ptr)
{
    do
    {
        while( (counter & 1) == 1 )
        { 
            usleep(100);
        }  

        pthread_mutex_lock(&mutex);
        printf("%d \n", counter);
        counter++;
        pthread_mutex_unlock(&mutex);

    } while( counter < 50 );
    pthread_exit( 0 );
} // end function: printfun2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM