Producer/consumer, consumer thread never executed - c++

Created a program having a producer thread and a consumer thread.
The producer thread continuously pushes to a stack every one second, which is protected by a mutex.
The consumer thread continuously pops from the stack.
The unexpected behavior is that, the producer thread is constantly running, while the consumer thread never gets a chance to pop the stack.
How could I proceed to investigate this problem? Many thanks.
#include <stack>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
std::mutex mtx;
std::stack<int> the_stack;
void producer(const int id)
{
while(1)
{
mtx.lock();
the_stack.push(0);
std::cout << "Producer " << id << " push" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
mtx.unlock();
}
}//producer
void consumer(const int id)
{
while(1)
{
mtx.lock();
if (!the_stack.empty())
{
std::cout << "Consumer " << id << " pop" << std::endl;
the_stack.pop();
}
mtx.unlock();
}
}//consumer
int main()
{
std::thread thread_0(producer, 0);
std::thread consum_0(consumer, 0);
thread_0.join();
consum_0.join();
return 0;
}//main;

The producer is spending its sleeping time while holding the mutex.
This hardly gives the consumer a chance to lock the mutex.
If you put the sleep statement outside the mutex protected area, it will work as expected..
void producer(const int id)
{
while(1)
{
....
mtx.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1)); // below the unlock operation
}

Related

If a thread that is blocked on a std::condition_variable is notified, but the lock on the associated mutex has not been released what would be result?

Is it clear what would happen if a thread blocked on a std::condition_variable receives a notification but the lock on the associated mutex is not yet released, and the lock will be released 10 seconds later? Would the thread wait for the lock to be released or is the situation undefined?
I added a 15seconds sleep on purpose to make the lock unavailable during that time to see how waiting thread will be doing. It is doing OK but just wanted to be sure about it.
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
struct SharedResource
{
SharedResource() :
cv_mutex(), cv(), counter(0)
{
}
/*
This mutex is used for three purposes:
1) to synchronize accesses to counter
2) to synchronize accesses to std::cerr
3) for the condition variable cv
*/
std::mutex cv_mutex;
std::condition_variable cv;
int counter;
};
void waits(SharedResource& sharedRes)
{
std::unique_lock<std::mutex> lk(sharedRes.cv_mutex);
std::cerr << "Waiting... \n";
while (sharedRes.counter != 1)
{
sharedRes.cv.wait_for(lk,3s);
std::cerr << "Thread ID: " << std::this_thread::get_id() << " wakes up every 3 seconds.\n";
}
std::cerr << "...finished waiting." << "counter: " << sharedRes.counter << std::endl;
} //The lk object will be unlocked after this scope ends.
void signals(SharedResource& sharedRes)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(sharedRes.cv_mutex);
std::cerr << "Notifying...\n";
} // The lk object will be unlocked after this scope ends.
sharedRes.cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(6));
{
std::lock_guard<std::mutex> lk(sharedRes.cv_mutex);
sharedRes.counter = 1;
std::cerr << "Notifying again...\n";
sharedRes.cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(15));
}// The lk object will be unlocked after this scope ends.
}
int main()
{
SharedResource sharedRes;
std::thread
t1(waits, std::ref(sharedRes)),
t2(signals, std::ref(sharedRes));
t1.join();
t2.join();
}
If a thread that is blocked on a std::condition_variable is notified, but the lock on the associated mutex has not been released what would be result?
It will continue to wait / wait_for until it can reacquire the lock.
When std::condition_variable::wait and wait_for returns (for whatever reason), the lock is held again, so you don't have to worry about that.
It can even return from wait without having gotten any notifications (spurious wake-ups) - but, no matter what, the lock is reacquired when the call returns.

Mutex does not work as I expect. What is my mistake?

I was trying to figure out the data race theme, and I made this code. Here we work with the shared element wnd. I thought that by putting lock in the while loop, I would prohibit the th1 thread from working with wnd, but this did not happen and I see an unobstructed output of the th1 thread.
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
std::thread th1([&]() {
int i = 0;
while (true)
{
++i;
if (wnd)
std::cout << i << " WND TRUE" << std::endl;
else
std::cout << i << " WND FALSE" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
while (true)
{
lock.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
if (wnd)
wnd = false;
else
wnd = true;
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
th1.join();
return 0;
}
To tell the truth, I was hoping to see that the th1 thread stops printing for 2+-seconds at a time when the main thread is inside the lock section.
You are not using the mutex and specially std::unique_lock properly.
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::thread th1{[&]() {
for (int i = 0; i<10000; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::cout << i << "\tWND\t " << std::boolalpha << wnd << std::endl;
};
}};
for (int i = 0; i<30; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
wnd = !wnd;
};
th1.join();
}
std::unique_lock uses its constructor operand as a resource whose acquisition is lock and release is unlock. It is designed to use RAII as a means of guaranteeing correct lock/unlock sequences on mutexes. a defered lock only means the mutex is not locked at the begining of lifespan of the std::unique_lock and it is not the usual use case. You can manually lock/unlock the mutex, but that generally leads to less maintainable, more error-prone code.
Keep in mind that if the threads involved are not racing over the ownership of the mutex, neither waits for the other; in your original prorgram, the worker thread did not touch the mutex. But in the program above, both threads are competing to lock the mutex; winner gets a chance to continue what he wants, and the loser has to wait until the mutex is unlocked - so that he can take its ownership.

Resolve deadlock issue, waiting in the main thread for multiple worker threads to finish (C++11)

I'm trying to write a program with c++11 in which multiple threads are run, and, during each cycle the main thread will wait for each thread to be finished. The program below is a testing program for this concept.
Apparently I'm missing something trivial in my implementation as it looks like I'm experiencing a deadlock (Not always, just during some random runs).
#include <iostream>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <condition_variable>
#include <mutex>
using namespace std;
class Producer
{
public:
Producer(int a_id):
m_id(a_id),
m_ready(false),
m_terminate(false)
{
m_id = a_id;
m_thread = thread(&Producer::run, this);
// ensure thread is available before it is started
this_thread::sleep_for(std::chrono::milliseconds(100));
}
~Producer() {
terminate();
m_thread.join();
}
void start() {
//cout << "start " << m_id << endl;
unique_lock<mutex> runLock(m_muRun);
m_ready = true;
runLock.unlock();
m_cond.notify_all();
}
void wait() {
cout << "wait " << m_id << endl;
unique_lock<decltype(m_muRun)> runLock(m_muRun);
m_cond.wait(runLock, [this]{return !m_ready;});
}
void terminate() {
m_terminate = true;
start();
}
void run() {
do {
unique_lock<decltype(m_muRun)> runLock(m_muRun);
m_cond.wait(runLock, [this]{return m_ready;});
if (!m_terminate) {
cout << "running thread: " << m_id << endl;
} else {
cout << "exit thread: " << m_id << endl;
}
runLock.unlock();
m_ready = false;
m_cond.notify_all();
} while (!m_terminate);
}
private:
int m_id;
bool m_ready;
bool m_terminate;
thread m_thread;
mutex m_muRun;
condition_variable m_cond;
};
int main()
{
Producer producer1(1);
Producer producer2(2);
Producer producer3(3);
for (int i=0; i<10000; ++i) {
cout << i << endl;
producer1.start();
producer2.start();
producer3.start();
producer1.wait();
producer2.wait();
producer3.wait();
}
cout << "exit" << endl;
return 0;
}
The program's output when the deadlock is occurring:
....
.......
running thread: 2
running thread: 1
wait 1
wait 2
wait 3
running thread: 3
Looking at the program's output when the deadlock occurs, I suspect the bottleneck of the program is that sometimes the Producer::wait function is called, before the corresponding thread is actually started, i.e. the command Producer::start should have triggered the start, a.k. unlocking of the mutex, however it is not yet picked up by the thread's run method (Producer::run), (NB: I'm not 100% sure of this!). I'm a bit lost here, hopefully somebody can provide some help.
You have race condition in this code:
runLock.unlock();
m_ready = false;
m_ready variable must be always protected by mutex for proper synchronization. And it is completely unnecessary to wait for thread to start this_thread::sleep_for() - proper synchronization would take care of that as well so you can simply remove that line. Note this is pretty inefficient way of doing proper multithreading - there should be thread pool instead of individual object with separate mutex and condition variable each.

C++14 thread/condition variable misunderstanding

I'm trying to run a thread with a function from a class member and use conditional variable to wait until the main thread signals and add the times the thread got signaled. Here is the code:
// Example program
#include <iostream>
#include <string>
#include <atomic>
#include <thread>
#include <unistd.h>
#include <mutex>
#include <condition_variable>
std::mutex m_mutex;
std::condition_variable m_condVar;
char stop =0;
class dummclass
{
std::thread dummclass_thread;
int alarms;
public:
dummclass() :
alarms(0),
dummclass_thread(std::thread(&dummclass::dummclassThreadProc, this))
{
}
~dummclass()
{
std::cout<<"Alarms: "<<alarms<<"\n";
//signal thread before joining
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
stop=1;
}
m_condVar.notify_one();
dummclass_thread.join();
}
private:
void dummclassThreadProc()
{
{
std::unique_lock<std::mutex> mlock(m_mutex);
std::cout<<"thread waiting\n";
m_condVar.wait(mlock);
std::cout<<"thread done waiting\n";
}
sleep(1);
std::unique_lock<std::mutex> mlock(m_mutex);
while (!stop)//!stop_dummclass.load())
{
std::cout<<"got mutex\n";
m_condVar.wait(mlock);
std::cout<<"wait done\n";
{
std::cout<<"got one\n";
alarms++;
}
}
std::cout<<"end loop\n";
}
};
int main()
{
dummclass *x = new dummclass;
sleep(3);
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
}
m_condVar.notify_one();
std::cout<<"done waiting\n";
sleep(3);
for(int i=0;i<13;i++)
{
{
std::cout<<"signal "<<i<<"\n";
std::lock_guard<std::mutex> lock_guard(m_mutex);
}
m_condVar.notify_one();
}
delete x;
}
The weird part is that the initial waiting and signaling that are outside of the loops actually work ok. I don't understand what mistake I do so that the while loop inside the class thread doesn't catch any signal from the main thread but it catches a signal from the destructor of the dummyclass when I delete it. This is the output:
thread waiting
done waiting
thread done waiting
got mutex
signal 0 signal 1 signal 2 signal 3 signal 4 signal 5 signal 6 signal 7 signal
8 signal 9 signal 10 signal 11 signal 12
Alarms: 0
wait done
got one end loop
EDIT: It seems that adding a 1 second sleep in the main() for loop solves the problem. Is it possible that the for loop gets the mutex before wait() manages to wake and lock the mutex ?
for(int i=0;i<13;i++)
{
{std::cout<<"signal "<<i<<"\n";
std::lock_guard<std::mutex> lock_guard(m_mutex);}
m_condVar.notify_one();
sleep(1);
}
Can someone please show me what is wrong ?
Thanks.
The object doing the waiting gets deleted before it processes the signal. Since the delete happens on a known to be running thread it has a fair chance to get executed first. In particular it is also likely to reacquire the lock again: Since the notify_one() is done while the mutex is locked the wait()ing thread cannot acquire it and will go back to sleep, waiting for the mutex to be released. That gives the signalling thread an opportunity to reacquire the lock. The only forced synchronizqtion causing the signalling thread to wait is the join() and it does give the waiting thread a chance to execute.
Note that signals of condition variables are not something delivered to the waiting thread. They are essentially wake-up calls. The waiting thread will wake up eventually once a signal is delivered. However, many signals can be delivered before it actually does so.
I don't understand what mistake I do so that the while loop inside the
class thread doesn't catch any signal from the main thread
Even though multiple notifications are sent the thread may only receive a single notification.
The notify_one() call does
not mean that the current thread will stop and wait for another thread.
It just means that the other thread must wake up at some point because something may have happened that it would be interested in.
Also note that std::condition_variable::wait could experience a spurious wakeup, so it might not even have anything to do or have received a 'real' signal.
The solution is to provide a predicate as a parameter to the wait() call. The predicate can then check if there is a signal (via a variable provided for this purpose and only changed under lock) and may also check if the program has been stopped.
In the updated program below I've added a predicate to the wait and made some minor changes. The program only notifies under lock, but you might choose not to.
// Example program - modified
#include <iostream>
#include <string>
#include <atomic>
#include <thread>
//#include <unistd.h>
#include <mutex>
#include <condition_variable>
#include <chrono>
std::mutex m_mutex;
std::condition_variable m_condVar;
bool signal_waiting{false};
bool stop{false};
class dummclass
{
int alarms{};
std::thread dummclass_thread{[this](){dummclassThreadProc(); }};
public:
~dummclass()
{
std::cout << "Alarms: " << alarms << "\n";
//signal thread before joining
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
stop = 1;
m_condVar.notify_one();
}
dummclass_thread.join();
}
private:
void dummclassThreadProc()
{
{
std::unique_lock<std::mutex> mlock(m_mutex);
std::cout << "thread waiting\n";
m_condVar.wait(mlock);
std::cout << "thread done waiting\n";
}
std::this_thread::sleep_for(std::chrono::seconds{1});
while(!stop)//!stop_dummclass.load())
{
std::unique_lock<std::mutex> mlock(m_mutex);
std::cout << "got mutex\n";
//m_condVar.wait(mlock);
m_condVar.wait(mlock, [](){return signal_waiting || stop; });
if(stop)
break;
std::cout << "wait done\n";
std::cout << "got one\n";
alarms++;
signal_waiting = false;
m_condVar.notify_one();
}
std::cout << "end loop\n";
}
};
int main()
{
dummclass *x = new dummclass;
//sleep(3);
std::this_thread::sleep_for(std::chrono::seconds{1});
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
m_condVar.notify_one();
}
std::cout << "done waiting\n";
//sleep(3);
std::this_thread::sleep_for(std::chrono::seconds{1});
for(int i = 0; i<13; i++)
{
{
std::cout << "signal " << i << "\n";
std::unique_lock<std::mutex> lock(m_mutex);
m_condVar.wait(lock, [](){return !signal_waiting ; });
signal_waiting = true;
m_condVar.notify_one();
}
}
delete x;
}

Why it does NOT occur deadlock?

The code is acquiring the same mutex from two different threads at the same time.
I understand that a deadlock should occur. Why it is not happening?
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
template <typename T>
class SafeQueue
{
public:
T pop()
{
std::unique_lock<std::mutex> mlock(mutex_);
std::cout << "lock pop()" << std::endl;
while (queue_.empty())
{
cond_.wait(mlock);
std::cout << "lock pop awake. Items: " << queue_.size() << std::endl;
}
auto item = queue_.front();
queue_.pop();
std::cout << "returning from pop" << std::endl;
return item;
}
void push(const T& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
std::cout << "lock push()" << std::endl;
queue_.push(item);
mlock.unlock();
cond_.notify_one();
}
private:
std::queue<T> queue_;
mutable std::mutex mutex_;
std::condition_variable cond_;
};
SafeQueue<int> queue;
void pop()
{
std::cout << "popping..." << std::endl;
std::cout << "popped: " << queue.pop() << std::endl;
}
int main()
{
std::thread consumerThread(pop);
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "main thread will push" << std::endl;
queue.push(2);
std::cout << "pushed" << std::endl;
consumerThread.join();
std::cout << "end" << std::endl << std::endl;
}
My output is:
popping...
lock pop()
main thread will push
lock push()
pushed
lock pop awake. Items: 1
returning from pop
popped: 2
end
This statement:
cond_.wait(mlock);
actually unlocks the mutex during the wait, and reacquires the lock once signaled. That's why you don't have any deadlock.
What is happening is that std::condition_variable::wait is releasing the mutex. The thread then waits until the notify_one call, that will release the condition and re-acquire the mutex.
http://en.cppreference.com/w/cpp/thread/condition_variable/wait
"There must be at least one thread that is waiting for a condition to become true. The waiting thread must first acquire a unique_lock. This lock is passed to the wait() method, that releases the mutex and suspends the thread until the condition variable is signaled. When that happens the thread is awaken and the lock is re-acquired."
http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
A deadlock requires TWO mutexes to be acquired in different orders in different threads. I only see a single mutex in your code.