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
#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;
}
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 shared variable shared_value
, we are synchronizing the even_thread_cs
and odd_thread_cs
.
Note that sleep is not used.
This is simple solution using single function.
#include <iostream>
#include <thread>
#include <condition_variable>
using namespace std;
mutex mu;
condition_variable cond;
int count = 1;
void PrintOddAndEven(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(PrintOddAndEven, true, n);
thread t2(PrintOddAndEven, false, n);
t1.join();
t2.join();
return 0;
}
I fail to understand why you want to use three separate threads for a serial behavior. But I will answer anyway:)
One solution would be to use a modified producer/consumer pattern with a prioritized queue between producers and consumers. The sort operation on the queue would depend on the integer value of the posted message. The consumer would peek an element in the queue and check if it is the next expected element. If not, it would sleep/wait.
A bit of 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));
}
}
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;
}
Solution using condition variable.
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex oddevenMu;
condition_variable condVar;
int number = 1;
void printEvenOdd(bool isEven, int maxnubmer)
{
unique_lock<mutex> ul(oddevenMu);
while (number < maxnubmer)
{
condVar.wait(ul, [&]() {return number % 2 == isEven;});
cout << number++ << " ";
condVar.notify_all();
}
}
int main(string args[])
{
thread oddThread(printEvenOdd, false, 100);
thread evenThread(printEvenOdd, true, 100);
oddThread.join();
evenThread.join();
return 0;
}