I want to implement semaphore class. And a user on stackoverflow has noted that my implementation is not working correct.
At the first I done it like this:
class sem_t {
int count;
public:
sem_t(int _count = 0) : count(_count) {};
void up() {
this->count++;
}
void down() {
while (this->count == 0)
std::this_thread::yield();
this->count--;
}
};
Then a user on stackoverflow noted that this implementation is faulty cause I read and write variable count out of any synchronization primitive and at some point the value can become incorrect and in case of compiler optimization compiler can assume that the variable count can not be modified by another thread. So, I tried to add mutex to this construction and I've done it like this:
class sem_t {
int count;
std::mutex mutualExclusion;
public:
sem_t(int _count = 0) : count(_count) {};
void up() {
this->mutualExclusion.lock();
this->count++;
this->mutualExclusion.unlock();
}
void down() {
this->mutualExclusion.lock();
while (this->count == 0)
std::this_thread::yield();
this->count--;
this->mutualExclusion.unlock();
}
};
But in case of using this approach when I try to detach thread i got an error saying that mutex has been destroyed while busy, cause one thread can hold mutex and then yield after which the thread is detached and error occurs (Is this solution ok?).
Then I tried to modify this code and I stoped on following construction:
class sem_t {
int count;
std::mutex mutualExclusion;
public:
sem_t(int _count = 0) : count(_count) {};
void up() {
this->mutualExclusion.lock();
this->count++;
this->mutualExclusion.unlock();
}
void down() {
while (this->count == 0)
std::this_thread::yield();
this->mutualExclusion.lock();
this->count--;
this->mutualExclusion.unlock();
}
};
But I think that this solution is faulty too, cause it can lead the same problem as the first solution.
So, whats the correct implementation?
I wanna note that I tried implementation with condition variable, but i am trying to implement semaphore without condition variable and if you want to suggest some solution with condition variable please describe how wait method of condition variable is working.
[Edit]
My full code, using self implemented semaphore:
#include "pch.h"
#include <iostream>
#include <vector>
#include <mutex>
#include <thread>
#include <chrono>
class sem_t {
int count;
std::mutex mutualExc;
public:
sem_t(int _count = 0) : count(_count) {};
void up() {
mutualExc.lock();
this->count++;
mutualExc.unlock();
}
void down() {
mutualExc.lock();
while (this->count == 0) {
mutualExc.unlock();
std::this_thread::yield();
mutualExc.lock();
}
this->count--;
mutualExc.unlock();
}
};
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
std::mutex mx;
std::mutex coutMX;
char philosopherState[N] = { THINKING };
sem_t philosopherSemaphores[N] = { 0 };
void testSetState(short i) {
if (philosopherState[i] == HUNGRY && philosopherState[(i + 1) % N] != EATING && philosopherState[(i + N - 1) % N] != EATING) {
philosopherState[i] = EATING;
philosopherSemaphores[i].up();
}
}
void take_forks(short i) {
::mx.lock();
philosopherState[i] = HUNGRY;
testSetState(i);
::mx.unlock();
philosopherSemaphores[i].down();
}
void put_forks(short i) {
::mx.lock();
philosopherState[i] = THINKING;
testSetState((i + 1) % N);
testSetState((i + N - 1) % N);
::mx.unlock();
}
void think(short p) {
for (short i = 0; i < 5; i++) {
coutMX.lock();
std::cout << "Philosopher N" << p << " is thinking!" << std::endl;
coutMX.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
void eat(short p) {
for (short i = 0; i < 5; i++) {
coutMX.lock();
std::cout << "Philosopher N" << p << " is eating!" << std::endl;
coutMX.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
void philosopher(short i) {
while (1) {
think(i);
take_forks(i);
eat(i);
put_forks(i);
}
}
int main()
{
std::vector<std::thread*> threadsVector;
for (int i = 0; i < N; i++) {
threadsVector.push_back(new std::thread([i]() { philosopher(i); }));
}
std::this_thread::sleep_for(std::chrono::milliseconds(15000));
for (int i = 0; i < N; i++) {
threadsVector[i]->detach();
}
return 0;
}
Error that is occurring (only occurs when running program in release or debug mode in visual studio)
The last attempt is indeed not correct because it may happend that several threads call down at the same time and all successfully pass
while (this->count == 0)
std::this_thread::yield();
lines and then they will all decrement the counter to possiby negative value:
this->mutualExclusion.lock();
this->count--;
this->mutualExclusion.unlock();
So, the counter value check and update must be performed atomically.
If you want to keep busy loop the easiest way would be just to call unlock before yield and lock after, so compare and decrement will be performed under the same lock:
void down() {
this->mutualExclusion.lock();
while (this->count == 0) {
this->mutualExclusion.unlock();
std::this_thread::yield();
this->mutualExclusion.lock();
}
this->count--;
this->mutualExclusion.unlock();
}
Also, you can use std::unique_lock guard which locks provided mutex in constructor and unlocks in destructor, so the mutex will not be accidentaly left in locked state:
void down() {
std::unique_lock<std::mutex> lock(this->mutualExclusion);
while (this->count == 0) {
lock.unlock();
std::this_thread::yield();
lock.lock();
}
this->count--;
}
To deal with "muxed destroyed while busy" error you need either to have a flag to stop background threads and wait for them to complete with join instead of detach:
#include <atomic>
...
std::atomic<bool> stopped{ false };
void philosopher(short i) {
while (!stopped) {
...
}
}
...
int main()
{
...
stopped = true;
for (int i = 0; i < N; i++) {
threadsVector[i]->join();
}
return 0;
}
or if you really don't want to care of releasing static resources you can call std::quick_exit instead of detach and return:
int main()
{
...
std::this_thread::sleep_for(std::chrono::milliseconds(15000));
std::quick_exit(0);
}
This is my code and I accidentally made a mistake buy not making the for loop longer but the code works as intended.
What happens after the program is completed? Does it have any fail cases or does the computer auto kill all thread and if there would be any additional code it Threads again would there be problems( for example if i would initiate 2 thread then there would be 6 thread working and the new thread ids would be 5 and 7?)
#include <iomanip>
#include <thread>
#include <iostream>
#include <mutex>
#include <sstream>
#include <vector>
#include <conio.h>
using namespace std;
bool endProgram = false;
struct Monitorius {
public:
int IOCounter = 0;
int readCounterC = 0;
int readCounterD = 0;
condition_variable cv;
mutex mtx;
int c = 10;
int d = 100;
Monitorius() {
c = 10;
d = 100;
IOCounter = 0;
readCounterC = 0;
readCounterD = 0;
}
void changeC(int i) {
while (!endProgram) {
unique_lock<mutex> lck(mtx);
cv.wait(lck, [&] {return readCounterC > 1; });
if (!endProgram) {
c += i;
readCounterC = 0;
cv.notify_all();
}
}
}
void changeD(int i) {
while (!endProgram) {
unique_lock<mutex> lck(mtx);
cv.wait(lck, [&] {return readCounterD > 1; });
if (!endProgram) {
d -= i;
readCounterD = 0;
cv.notify_all();
}
}
}
void readCD(int i) {
int oldC = -1;
int oldD = -1;
while (!endProgram) {
unique_lock<mutex> lck(mtx);
cv.wait(lck, [&] {return oldC != c && oldD != d; });
if (!endProgram) {
stringstream str;
str << i << ": c:" << c << " d: " << d << endl;
cout << str.str();
readCounterC++;
readCounterD++;
IOCounter++;
if (IOCounter >= 15)
endProgram = true;
cv.notify_all();
oldC = c;
oldD = d;
}
}
}
};
int main()
{
Monitorius M;
vector<thread> myThreads;
myThreads.reserve(5);
myThreads.emplace_back([&] { M.changeC(1); });
myThreads.emplace_back([&] { M.changeD(2); });
myThreads.emplace_back([&] { M.readCD(3); });
myThreads.emplace_back([&] { M.readCD(4); });
myThreads.emplace_back([&] { M.readCD(5); });
for (size_t i = 0; i < 1; i++)
myThreads[i].join();
_getch();
}
When your main function exits, all the threads in the vector will be destructed.
If they are not joined at that time std::terminate should be called by the std::thread destructor.
By detaching threads the thread-objects can be destructed and the thread still continues to run. But then on the common modern operating systems when the process ends (which happens after main have returned or exit is called) the threads will be killed anyway. To let threads continue running even after the "main" thread ends, you have to call a system-dependent function to exit the "main" thread.
I do not know if it's possible to do this on Windows though, as the ExitThread function should not be used by C++ code as it exits the thread without destructing objects.
The solution to both problems is of course to properly join all threads.
I have used std::sthread for background image loading. I create background job as this:
if (bgThreads.size() > MAX_THREADS_COUNT){
fclose(file);
return;
}
if (bgThreads.find(id) != bgThreads.end()){
fclose(file);
return;
}
std::shared_ptr<BackgroundPNGLoader> bg = std::make_shared<BackgroundPNGLoader>(file, id);
bgThreads[id] = bg;
bg->thread = std::thread(&BackgroundPNGLoader::Run, bg);
In BackgroundPNGLoader, I have:
struct BackgroundPNGLoader{
std::atomic<bool> finished;
FILE * f;
int id;
BackgroundPNGLoader() : finished(false) {}
void Run(){
///.... load data
finished.store(true);
}
}
In my main app, I have Update - Render loop running in main thread. In Update, I have:
std::list<int> finished;
for (auto & it : bgThreads)
{
if (it.second->finished)
{
if (it.second->thread.joinable())
{
it.second->thread.join();
}
finished.push_back(it.first);
//fill image data to texture or whatever need to be done on main thread
fclose(it.second->f);
}
}
for (auto & it : finished)
{
bgThreads.erase(it);
}
Is this considered safe? I am a little worried about spawning new threads every time I need new file open, there is no max limit.
First, avoid fopen/fclose and use C++' file I/O instead to avoid potential resource leaks when exceptions are thrown. Further, using a raw std::thread isn't necessary in most cases. For asynchronous tasks, std::async combined with futures is is the thing to go with.
std::async returns a potential result within a std::future, which can be retrieved later:
#include <future>
#include <thread>
#include <chrono>
#include <array>
#include <iostream>
#include <random>
size_t doHeavyWork(size_t arg)
{
std::mt19937 rng;
rng.seed(std::random_device()());
std::uniform_int_distribution<unsigned int> rnd(333, 777);
//simulate heavy work...
std::this_thread::sleep_for(std::chrono::milliseconds(rnd(rng)));
return arg * 33;
}
//wrapper function for checking whether a task has finished and
//the result can be retrieved by a std::future
template<typename R>
bool isReady(const std::future<R> &f)
{
return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
int main()
{
constexpr size_t numTasks = 5;
std::array<std::future<size_t>, numTasks> futures;
size_t index = 1;
for(auto &f : futures)
{
f = std::async(std::launch::async, doHeavyWork, index);
index++;
}
std::array<bool, numTasks> finishedTasks;
for(auto &i : finishedTasks)
i = false;
size_t numFinishedTasks = 0;
do
{
for(size_t i = 0; i < numTasks; ++i)
{
if(!finishedTasks[i] && isReady(futures[i]))
{
finishedTasks[i] = true;
numFinishedTasks++;
std::cout << "task " << i << " ended with result " << futures[i].get() << '\n';
}
}
}
while(numFinishedTasks < numTasks);
std::cin.get();
}
std::async may launch separate threads using a thread pool.
First, you better do not spawn more threads than cores.
Here is a simple example using detach and letting threads informing about their statuses:
#include<thread>
#include<atomic>
struct task_data
{
};
void doHeavyWork(task_data to_do, std::atomic<bool>& done)
{
//... do work
//---
//--
done = true;
}
int main()
{
unsigned int available_cores = std::thread::hardware_concurrency();//for real parallelism you should not spawn more threads than cores
std::vector<std::atomic<bool>> thread_statuses(available_cores);
for (auto& b : thread_statuses)//initialize with all cores/threads are free to use
b = true;
const unsigned int nb_tasks = 100;//how many?
std::vector<task_data> tasks_to_realize(nb_tasks);
for (auto t : tasks_to_realize)//loop on tasks to spawn a thread for each
{
bool found = false;
unsigned int status_id = 0;
while (!found) //loop untill you find a core/thread to use
{
for (unsigned int i = 0; i < thread_statuses.size(); i++)
{
if (thread_statuses[i])
{
found = true;
status_id = i;
thread_statuses[i] = false;
break;
}
}
}
//spawn thread for this task
std::thread task_thread(doHeavyWork, std::move(t), std::ref(thread_statuses[status_id]));
task_thread.detach();//detach it --> you will get information it is done by it set done to true!
}
//wait till all are done
bool any_thread_running = true;
while (any_thread_running)//keep untill all are done
{
for (unsigned int i = 0; i < thread_statuses.size(); i++)
{
if (false == thread_statuses[i])
{
any_thread_running = true;
break;
}
any_thread_running = false;
}
}
return 0;
}
I am interesting whether mutexes(not depending on particular language) must keep the order of lock/unlock?
Here is example C++ code:
std::mutex testVecMtx;
std::vector<int> testVec;
void testPush(int v){
std::lock_guard<std::mutex> lk(testVecMtx);
if (testVec.empty()){
// wait some time to get more threads waiting on testVecMtx
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
}
testVec.push_back(v);
}
void Main_TEST(){
std::list<std::thread> thList;
for (int i = 0; i < 1000; i++){
thList.push_front(std::thread(testPush, i));
}
for (auto &i : thList){
if (i.joinable()){
i.join();
}
}
bool ok = true;
for (int i = 0; i < (testVec.size() - 1) && ok; i++){
ok = testVec[i + 1] - testVec[i] == 1;
}
if (ok){
int stop = 243; // 1st breaking point here...
}
else{
int stop = 432; // ...and 2nd here
}
}
After running this code in VS2013 serveral times in Debug and Release(with some changes to get code not optimized out) mode I always get hit only on 1st breakpoint.
No, there are no guarantees about the order. It just happens to work this way on your machine(for instance, on my computer ok is not always true).
No, there are no guarantees about the order.
You can try with condition variables:
#include <thread>
#include <vector>
#include <array>
#include <list>
#include <mutex>
#include <condition_variable>
const int MAX = 100; //***
std::mutex testVecMtx;
std::vector<int> testVec;
std::array<std::condition_variable,MAX+1> Notifications; //***
int Current = 0; //***
void testPush(int v){
std::unique_lock<std::mutex> lk(testVecMtx);
while (v != Current){
Notifications[v].wait(lk);
}
testVec.push_back(v);
Current++;
if (v != MAX)
Notifications[v+1].notify_all();
}
int main(){
std::list<std::thread> thList;
for (int i = 0; i < MAX; i++){
thList.push_front(std::thread(testPush,i));
}
for (auto &i : thList){
i.join();
}
bool ok = true;
for (int i = 0; i < (testVec.size() - 1) && ok ;i++){
ok = (testVec[i + 1] - testVec[i]) == 1;
}
if (ok){
int stop = 243; // 1st breaking point here...
// std::cout<<"Ok"<<std::endl;
}
else{
int stop = 432; // ...and 2nd here
}
}
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 semaphore. even 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 are generating only number and there is a third thread T3 which is going to print those numbers then what should be ideal design ? I used an array where odd number will be placed at odd place and even number will be place at even position. T3 will read from this array this will avoid any thread saftey over this array and if T3 does not find any index then it will wait till that index gets populated. Another solution can be to use a queue which will have a mutex which can be used by T1 and T2 while insertion.
Please comment on this solution and how can i make it more efficient.
Edit to make problem much clear: Overall problem is that I have two producers (T1,T2) and a single consumer (T3), and my producers are interdependent.
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;
}
#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;
}
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;
}
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;
}
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
std::mutex m;
int count = 0;
void printEven()
{
cout << "Entered Even\n" << endl;
while(count <= 10)
{
m.lock();
if(count%2 == 0)
cout << count++ << " ";
m.unlock();
}
}
void printOdd()
{
cout << "Entered Odd" << endl;
while(count < 10)
{
m.lock();
if(count%2 == 1)
cout << count++ << " ";
m.unlock();
}
}
int main()
{
std::thread t1(printOdd);
std::thread t2(printEven);
t1.join();
t2.join();
return 0;
}
#include "threadFunc.hpp"
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex t1;
condition_variable cond;
int number = 11;
int count = 0;
void printEven()
{
while(1)
{
unique_lock<mutex> ul(t1);
if(count< number)
{
if(count % 2 != 0)
{
cond.wait(ul);
}
cout<<count<<" : printed by thread"<<this_thread::get_id()<<endl;
count++;
}
if(count > number)
break;
ul.unlock();
cond.notify_all();
}
}
void printOdd()
{
while(1)
{
unique_lock<mutex> ul(t1);
if(count< number)
{
if(count % 2 == 0)
{
cond.wait(ul);
}
cout<<count<<" : printed by thread"<<this_thread::get_id()<<endl;
count++;
}
if(count > number)
break;
ul.unlock();
cond.notify_all();
}
}
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));
}
}
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.
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.
#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;
}
This code will work . I have tested it on visual studio 2017
#include "stdafx.h"
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
int num = 1;
void oddThread() {
for (; num < 10;) {
unique_lock<mutex> lg(m);
cv.wait(lg, [] {return (num % 2 ==1); });
cout << "From odd Thread " << num << endl;
num++;
lg.unlock();
cv.notify_one();
}
}
void evenThread() {
for (; num < 100;) {
unique_lock<mutex> lg(m);
cv.wait(lg, [] {return (num % 2 == 0); });
cout << "From even Thread " << num << endl;
num++;
lg.unlock();
cv.notify_one();
}
}
int main() {
thread t1{ oddThread}; //odd function thread
thread t2{ evenThread};
t1.join();
t2.join();
cin.get();
return 0;
}
output
from oddThread: 1
from evenThread: 2
from oddThread: 3
from evenThread: 4
from oddThread: 5
from evenThread: 6
from oddThread: 7
from evenThread: 8
from oddThread: 9
from evenThread: 10
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex m;
std::condition_variable cv;
int counter =1;
void printEven()
{
std::unique_lock<std::mutex> lk(m);
while(1)
{
if(counter > 10)
break;
if(counter %2 != 0)
{
cv.wait (lk);
}
else
{
cout << "counter : " << counter << endl;
counter++;
//lk.unlock();
cv.notify_one();
}
}
}
void printOdd()
{
std::unique_lock<std::mutex> lk(m);
while(1)
{
if(counter > 9)
break;
if(counter %2 == 0)
{
cv.wait (lk);
}
else
{
cout << "counter : " << counter << endl;
counter++;
//lk.unlock();
cv.notify_one();
}
}
}
int main()
{
std::thread t1(printEven);
std::thread t2(printOdd);
t1.join();
t2.join();
cout << "Main Ends" << endl;
}
i have used anonymous func (lambda) to do this and clubbed cond variable and mutex.
#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
using namespace std;
int main() {
int count = 1;
mutex mtx;
condition_variable condition;
const int ITERATIONS = 20; // iterations
//prints odd numbers
thread t1([&]() {
while (count < ITERATIONS)
{
unique_lock <mutex> lock(mtx);
condition.wait(lock, [&]() {
return count % 2 != 0;
});
cout << "thread1 prints: " << count << endl;
count++;
lock.unlock();
condition.notify_all();
}
});
thread t2([&]
{
while (count < ITERATIONS)
{
unique_lock <mutex> lock(mtx);
condition.wait(lock, [&]() {
return count % 2 == 0;
});
cout << "thread2 prints: " << count << endl;
count++;
lock.unlock();
condition.notify_all();
}
});
t1.join();
t2.join();
}
#include <bits/stdc++.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
unique_lock<mutex> lck(m);
void *printeven(void *arg)
{
int *n = (int *)arg;
while (*n <= 100)
{
cv.wait(lck);
*n = *((int *)arg);
cout << this_thread::get_id() << " : " << *n << endl;
*n = *n + 1;
cv.notify_one();
}
exit(0);
}
void *printodd(void *arg)
{
int *n = (int *)arg;
while (*n <= 100)
{
*n = *((int *)arg);
cout << this_thread::get_id() << " : " << *n << endl;
*n = *n + 1;
cv.notify_one();
cv.wait(lck);
}
exit(0);
}
int main()
{
int num = 1;
pthread_t p1 = 1;
pthread_t p2 = 2;
pthread_create(&p1, NULL, printodd, &num);
pthread_create(&p2, NULL, printeven, &num);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
return 0;
}
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable even_to_odd;
std::condition_variable odd_to_even;
unsigned int count = 1;
constexpr int MAX_COUNT = 20;
void even(int n) {
for (int i = n; i <= MAX_COUNT; i++) {
std::unique_lock<std::mutex> lock(mtx);
if (i %2 == 0) {
odd_to_even.wait(lock);
std::cout << "Even: " << i << std::endl;
even_to_odd.notify_one();
}
}
}
void odd(int n) {
for (int i = n; i <= MAX_COUNT; i++) {
std::unique_lock<std::mutex> lock(mtx);
if (i == 1) {
std::cout << "Odd : " << i << std::endl;
odd_to_even.notify_one();
}
else if (i % 2 != 0) {
even_to_odd.wait(lock);
std::cout << "Odd : " << i << std::endl;
odd_to_even.notify_one();
}
}
}
int main() {
std::thread thread1(even,count);
std::thread thread2(odd,count);
thread1.join();
thread2.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.