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
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;
}
Solution is based on C++11 critical code section aka mutex.
Here's the working code, followed by an explanation.
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;
}
}
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.
#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;
}
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.