printing odd and even number printing alternately using threads in C++

前端 未结 10 1092
后悔当初
后悔当初 2021-01-03 02:09

Odd even number printing using thread I came across this question and wanted to discuss solution in C++ . What I can think of using 2 binary semaphores odd and even semapho

相关标签:
10条回答
  • 2021-01-03 03:05

    This is the easiest solution you can refer:

    #include<iostream>
    #include<mutex>
    #include<pthread.h>
    #include<cstdlib>
    int count=0;
    using namespace std;
    mutex m;
    void* printEven(void *a)
    {
       while(1)
       {
           m.lock();
           if(count%2==0)
           {
              cout<<" I am Even"<<count<<endl;
              count++;
           }
           if(count==100)
               break;
           m.unlock();
       }
    }
    void* printOdd(void *b)
    {
        while(1)
        {
           m.lock();
           if(count%2!=0)
           {
               cout<<"I am odd"<<count<<endl;
               count++;
           }
           if(count>100)
              break;
           m.unlock();
        }
     }
     int main()
     {
         int *ptr = new int();
         pthread_t thread1, thread2;
         pthread_attr_t attr;
         pthread_attr_init(&attr);
         pthread_create(&thread1,&attr,&printEven,NULL);
         pthread_create(&thread2,&attr,&printOdd, NULL);
         pthread_join(thread1,&ptr);
         pthread_join(thread2,&ptr);
         delete ptr;
     }
    
    0 讨论(0)
  • 2021-01-03 03:06

    Solution is based on C++11 critical code section aka mutex.

    Here's the working code, followed by an explanation.

    Tested and working on VS2013:

    using namespace std;
    #include <iostream>
    #include <string>
    #include <thread>
    #include <mutex>
    
    std::mutex mtx;
    
    void oddAndEven(int n, int end);
    
    int main()
    {
    std::thread odd(oddAndEven, 1, 10);
    std::thread Even(oddAndEven, 2, 10);
    
    odd.join();
    Even.join();
    
    return 0;
    }
    
    
    
    void oddAndEven(int n, int end){
    int x = n;
    for (; x < end;){
        mtx.lock();
        std::cout << n << " - " << x << endl;
        x += 2;
        mtx.unlock();
        std::this_thread::yield();
        continue;
     }
    }
    

    i.e:

    Thread odd goes to method oddAndEven with starting number 1 thus he is the odd. He is the first to acquire the lock which is the mtx.lock().

    Meanwhile, thread Even tries to acquire the lock too but thread odd acquired it first so thread Even waits.

    Back to thread odd (which has the lock), he prints the number 1 and releases the lock with mtx.unlock(). At this moment, we want thread Even to acquire lock and to print 2 so we notify thread Even by writing std::this_thread::yield(). Then thread Even does the same.

    etc etc etc.

    0 讨论(0)
  • 2021-01-03 03:06
     #include  <stdio.h>
     #include  <stdlib.h>
     #include  <iostream>
     #include  <pthread.h>
     #include  <semaphore.h>
    
      sem_t sem;
      sem_t sem2;
      using namespace std ;
    
    int count = 1;
    
    void increment(int x)
    {
        cout << "called by thread : " << x << "count is : " << count ++ << "\n";
    }
    
    void *printAltmessage1(void *thread_value)
    {
        for(int m=0; m < (*(int *)thread_value); m++)
        {
            if (sem_wait(&sem) == 0)
            {
                cout << " Thread printAltmessage1 is executed" <<"\n";  
                increment(1);
                sem_post(&sem2);
            }
        }
    }
    
    void *printAltmessage2(void *thread_value)
    {
        for(int m=0; m < (*(int *)thread_value); m++)
        {
            if (sem_wait(&sem2) == 0)
            {
                cout << " Thread printAltmessage2 is executed" <<"\n";
                increment(2);  
                sem_post(&sem);
            }
        }
    }
    
    int main()
    {
         sem_init(&sem,0, 1);
         sem_init(&sem2,0, 0);
         pthread_t threads[2];
         int x =8;
         for(int i=0;i<2;i++)
         {
              if(i==0)
              int rc =pthread_create(&threads[i],NULL,printAltmessage1,(void*)&x);
              else
              int rc =pthread_create(&threads[i],NULL,printAltmessage2,(void*)&x);
          }
          pthread_exit(NULL);
          return 0;
    }
    
    0 讨论(0)
  • 2021-01-03 03:09

    As a first thing, the two functions should a least contain a loop, (unless you just want a single number)

    A more standard solution (which remaps your idea) is to have a global structure containing a a mutex, and two condition variables (odd and even) plus a return value, and another condition for the printing. than use a uique_lock to handle the synchronization.

    IN PSEUDOCODE:

    struct global_t
    {
        mutex mtx;
        int value = {0};
        condition_variable be_odd, be_even, print_it;
        bool bye = {false};
    
        global_t() { be_odd.notify(); }
    } global;
    
    void odd_generator()
    {
        int my_odd = 1;
        for(;;)
        {
            unique_lock lock(global.mtx);
            if(global.bye) return;
            global.be_odd.wait(lock);
            global_value = my_odd; my_odd+=2;
            global.print_it.notify();
            if(my_odd > 100) bye=true;
        } //let RAII to manage wait states and unlocking
    };
    
    void even_generator()
    { /* same as odd, with inverted roles */ }
    
    void printer()
    {
        for(;;)
        {
            unique_lock lock(global.mtx);
            if(bye) return;
            global.ptint_it.wait(lock);
            std::cout << global.value << std::endl;
            ((global.value & 1)? global.be_even: global.be_odd).notify();
        }
    }
    
    
    int main()
    {
        thread oddt(odd_generator), event(even_generator), printt(printer);
        oddt.join(), event.join(), printer.join();
    }
    

    Note that, apart didactic purpose, this solution adds no value respect to a simple loop printing the value of a counter, since there will never be real concurrency.

    Note also (to avoid globals) that you can wrap everything into a class (making the actual main a class method) and instantate that class on the stack inside the new main.

    0 讨论(0)
提交回复
热议问题