Printing odd and even printing using streams in C ++

Odd printing even using stream I came across this question and wanted to discuss a C ++ solution. What can I think of using 2 odd binary semaphores and even semaphores. even a semaphore initialized to 1 and odd initialized to 0.

**T1 thread function** 
funOdd()
{  
  wait(even)  
  print odd;  
  signal(odd)  
}


**T2 thread function**
funEven()  
{  
  wait(odd)  
  print even  
  signal(even)  
}  

      

In addition to this, if my functions only generate a number, and there is a third T3 thread that is going to print those numbers, then what would the ideal design be? I used an array where the odd number will be placed in the odd position, and even the number will be placed in the even position. T3 will read from this array, this will avoid any thread safety over this array, and if T3 doesn't find any index, it will wait until that index is populated. Another solution could be to use a queue that will have a mutex that can be used by T1 and T2 on insert.

Please comment on this solution and how I can make it more efficient.

Edit to make the problem clearer. ... A common problem is that I have two producers (T1, T2) and one consumer (T3) and my producers are interdependent.

+4


source to share


9 replies


Using condition_variable



#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mu;
std::condition_variable cond;
int count = 1;

void PrintOdd()
{
    for(; count < 100;)
    {
        std::unique_lock<std::mutex> locker(mu);
        cond.wait(locker,[](){ return (count%2 == 1); });
        std::cout << "From Odd:    " << count << std::endl;
        count++;
        locker.unlock();
        cond.notify_all();
    }

}

void PrintEven()
{
    for(; count < 100;)
    {
        std::unique_lock<std::mutex> locker(mu);
        cond.wait(locker,[](){ return (count%2 == 0); });
        std::cout << "From Even: " << count << std::endl;
        count++;
        locker.unlock();
        cond.notify_all();
    }
}

int main()
{
    std::thread t1(PrintOdd);
    std::thread t2(PrintEven);
    t1.join();
    t2.join();
    return 0;
}

      

+2


source


The solution is based on the C ++ 11 aka mutex critical code section .

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

      

those:



The odd thread goes to the oddAndEven method with a starting number of 1, so it is odd. He first acquired the castle, which is mtx.lock()

.

Meanwhile, the Even thread is trying to acquire the lock, but the odd thread acquired it first, so the Even thread is waiting.

Back to topic odd (which has a lock), it prints the number 1 and releases the lock with mtx.unlock()

. At this point, we want the thread to even acquire the lock and print 2, so we notify the thread Even by writing std::this_thread::yield()

. Then the Even stream does the same.

etc. etc. etc.

+1


source


This is the simplest solution you can use:

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

      

+1


source


I don't understand why you want to use three separate threads for consistent behavior. But I will answer anyway :)

One solution would be to use a modified producer / consumer pattern with priority queuing between producers and consumers. The sorting operation on the queue will depend on the integer value of the posted message. The consumer will peek into the queue and check if this is the next expected item. If not, he will sleep / wait.

Some code:

class Elt implements Comparable<Elt> {
  int value;
  Elt(value) { this.value=value; }
  int compare(Elt elt);
}

class EltQueue extends PriorityBlockingQueue<Elt> { // you shouldn't inherit colelctions, has-a is better, but to make it short
  static EltQueue getInstance(); // singleton pattern
}

class Consumer{
  Elt prevElt = new Elt(-1);
  void work()
  {
    Elt elt = EltQueue.getInstance().peek();
    if (elt.getValue() == prevElt.getValue()+1)) {
      EltQueue.getInstance().poll();
      //do work on Elt
    }
  }
}

class Producer {
  int n=0; // or 1!
  void work() {
    EltQueue.getInstance().put(new Elt(n+=2));
  }
}

      

0


source


As the first thing, the two functions must contain at least a loop (unless you just want the same number)

A more standard solution (which reassigns your idea) is to have a global structure containing the mutex and two condition variables (odd and even) plus a return value and another printable condition. than using uique_lock to handle 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 from the didactic purpose, this solution does not add any value to a simple loop printing the counter value, as there will never be real concurrency.

Note also (to avoid global bindings) that you can wrap everything in a class (by making the main method of the class) and create that class on the stack inside a new main one.

0


source


 #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


source


#include <iostream>
#include <thread>
#include <mutex>

std::mutex mu;
unsigned int change = 0;

void printConsecutiveNumbers(int start, int end,unsigned int consecutive)
{
    int x = start;
    while (x < end)
    {
        //each thread has check there time is coming or not
        if (change % consecutive == start)
        {
            std::unique_lock<std::mutex> locker(mu);
            std::cout << "Thread " << start << " -> " << x << std::endl;
            x += consecutive;
            change++;
            //to counter overflow
            change %= consecutive;
        }
    }
}

int main()
{
    //change num = 2 for printing odd and even
    const int num = 7;
    const int endValue = 1000;
    std::thread threads[num];
    //Create each consecutive threads
    for (int i = 0; i < num; i++)
    {
        threads[i] = std::thread(printConsecutiveNumbers, i, endValue, num);
    }

    //Joins all thread to the main thread
    for (int i = 0; i < num; i++)
    {
        threads[i].join();
    }

    return 0;
}

      

0


source


This is a simple solution using one function.

#include <iostream>
#include <thread>
#include <condition_variable>
using namespace std;

mutex mu;
condition_variable cond;
int count = 1;

void PrintOddEven(bool even, int n){
    while(count < n){
        unique_lock<mutex> lk(mu);
        cond.wait(lk, [&](){return count%2 == even;});
        cout << count++ << " ";
        lk.unlock();
        cond.notify_all();
    }
}

int main() {
    int n = 10;
    thread t1(PrintOddEven, true, n);
    thread t2(PrintOddEven, false, n);

    t1.join();
    t2.join();
    return 0;
}

      

0


source


Please see below working code (VS2005)

#include <windows.h>
#include <stdlib.h>

#include <iostream>
#include <process.h>

#define MAX 100
int shared_value = 0;

CRITICAL_SECTION cs;

unsigned _stdcall even_thread_cs(void *p)
{

    for( int i = 0 ; i < MAX ; i++ )
    {
        EnterCriticalSection(&cs);

        if( shared_value % 2 == 0 )
        {
            printf("\n%d", i);
        }


        LeaveCriticalSection(&cs);

    }
    return 0;
}

unsigned _stdcall odd_thread_cs(void *p)
{
    for( int i = 0 ; i < MAX ; i++ )
    {
        EnterCriticalSection(&cs);

        if( shared_value % 2 != 0 )
        {
            printf("\n%d", i);
        }

        LeaveCriticalSection(&cs);  

    }

    return 0;
}


int main(int argc, char* argv[])
{
     InitializeCriticalSection(&cs);

    _beginthreadex(NULL, NULL, even_thread_cs, 0,0, 0);
    _beginthreadex(NULL, NULL, odd_thread_cs, 0,0, 0);

    getchar();
    return 0;
}

      

Here, using a shared variable shared_value

, we synchronize even_thread_cs

and odd_thread_cs

. Please note that sleep is not used.

-2


source







All Articles