Here is my source code:
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include "thread"
#include "mutex"
int count0=0 ,count1 =0;
std::mutex main_thread;
std::unique_lock<std::mutex> lck(main_thread, std::defer_lock);
void Function00(long millisecond){
while (true){
lck.lock();
count1++;
printf("count0:%d count1:%d \n",count0,count1);
lck.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(millisecond));
}
}
void Function01(){
std::thread th(Function00, 1000);//count per 1 s
do{
lck.lock();
count0++;
lck.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(500));//count per 0.5 s
} while (1);
}
int main(int argc, char *argv[])
{
Function01();
return 0;
}
I then use the command to build my .o file:
g++ -std=c++11 -pthread testa.cpp -o a.o
However, it shows the error:
terminate called after throwing an instance of 'std::system_error'
what(): Resource deadlock avoided
Aborted
I feel confuse and no idea to solve it, so i try in Microsoft VS2013, and it runs with no error... I feel confuse to it. Is it the problem in linux? What should i modify to prevent the deadlock?
unique_lock cannot be locked twice, if you want to lock a mutex on two threads so that one of them will block, you need to use two unique_locks.
void Function00(long millisecond){
while (true){
{
std::unique_lock<std::mutex> lck(main_thread);
count1++;
printf("count0:%d count1:%d \n",count0,count1);
}
std::this_thread::sleep_for(std::chrono::milliseconds(millisecond));
}
}
void Function01(){
std::thread th(Function00, 1000);//count per 1 s
do{
{
std::unique_lock<std::mutex> lck(main_thread);
count0++;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));//count per 0.5 s
} while (1);
}
Related
#include <iostream>
#include<thread>
#include <initializer_list>
#include <vector>
#include <future>
#include <time.h>
using namespace std;
class Gadget{
public:
Gadget(){
flag_ = false;
cout<<"Creating new Gadgets"<<endl;
}
void wait(){
while(flag_==false){
cout<<"waiting here...."<<endl;
this_thread::sleep_for(chrono::milliseconds(1000));
}
}
void wake(){
flag_ = true;
}
private:
volatile bool flag_;
};
I am trying to make two threads and one thread will sleep for 1 sec after checking the flag value. As i have made flag volatile it should change at some point. But the program is waiting infinitely.
int main() {
Gadget g;
thread t(&Gadget::wait,g);
thread s(&Gadget::wake,g);
t.join();
s.join();
cout<<"Ending the program "<<endl;
return 0;
}
volatile isn't for variables that are changed by the program itself. It's for variables that changes outside the program's control - like if it's directly connected to hardware.
Your main problem is however that you pass g by value so the two threads are working on different copies of your original g.
So, change to
std::atomic<bool> flag_;
and
thread t(&Gadget::wait, &g);
thread s(&Gadget::wake, &g);
Also worth mentioning: The two methods will not necessarily run in the order you start them, so waiting here.... may or may not show up.
Edit:
As mentioned in the comments: When waiting for a condition you should usually use a std::condition_variable. I've made an example of how that could look. I've also moved the starting of the threads into Gadget which makes it more obvious which object the thread is working on.
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
class Gadget {
public:
Gadget() { std::cout << "Creating new Gadget\n"; }
// new interface for starting threads
std::thread start_wait() { return std::thread(&Gadget::wait, this); }
std::thread start_wake() { return std::thread(&Gadget::wake, this); }
private:
void wait() {
std::unique_lock<std::mutex> ul(mutex_);
std::cout << "wait: waiting here...\n";
// Read about "spurious wakeup" to understand the below:
while(not flag_) cond_.wait(ul);
// or:
// cond_.wait(ul, [this] { return flag_; });
std::cout << "wait: done\n";
}
void wake() {
// simulate some work being done for awhile
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
{ // lock context start
std::lock_guard<std::mutex> lg(mutex_);
flag_ = true;
std::cout << "wake: notifying the waiting threads\n";
} // lock context end
// notify all waiting threads
cond_.notify_all();
}
std::condition_variable cond_;
std::mutex mutex_;
bool flag_ = false; // now guarded by a mutex instead
};
int main() {
Gadget g;
// start some waiting threads
std::vector<std::thread> threads(16);
for(auto& th : threads) th = g.start_wait();
// and one that wakes them up
auto th_wake = g.start_wake();
for(auto& th : threads) th.join();
th_wake.join();
std::cout << "Ending the program\n";
}
so i want the program to ouput 1\n2\n1\n2\n1\n2\n but it seems to get stuck somewhere. But when i debug it and set a breackpoint at cv1.notify_one() right after declaring t2 it executes ??
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
mutex cout_lock;
condition_variable cv1, cv2;
mutex mtx1;
unique_lock<std::mutex> lck1(mtx1);
mutex mtx2;
unique_lock<std::mutex> lck2(mtx2);
const int COUNT = 3;
int main(int argc, char** argv)
{
thread t1([&](){
for(int i = 0; i < COUNT; ++i)
{
cv1.wait(lck1);
cout << "1" << endl;
cv2.notify_one();
}
});
thread t2([&](){
for(int i = 0; i < COUNT; ++i)
{
cv2.wait(lck2);
cout << "2" << endl;
cv1.notify_one();
}
});
cv1.notify_one();
t1.join();
t2.join();
return 0;
}
There are several flaws:
You want to guard your output. Therefor you need just one mutex so only one thread can do their work at a time.
You are potentially missing out notifications to your condition variables.
Your global unique_locks aquire the locks of the mutexs in their constructors. So you are holding the locks the whole time and no thread can make progress. Your global unique_locks aquire the locks of the mutexs in their constructors. This is done in the main thread. T1 and T2 are unlocking them through the condition_variable. This is undefined behaviour (thread that owns mutex must unlock it).
This is a recipe to use the condition variable approach correctly:
Have a condition you are interested in. In this case some kind of variable to remember who's turn it is.
Guard this variable by a (ONE!) mutex
Use a (ONE!) condition_variable in conjunction with the mutex of point 2 and the condition of point 1.
This ensures:
There is at any time only one thread which can look and/or change the condition you have.
If a thread is reaching the point in code where it possibly waits for the condition variable, it first checks the condition. Maybe the thread does not even need to go to sleep since the condition he wanna wait for is already true. To do so, the thread has to aquire the mutex, check the condition and decides what to do. While doing so, he owns the lock. The condition cant change because the thread has the lock itself. So you cant miss out a notification.
This leads to the following code ( see live here ):
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
int main(int argc, char** argv)
{
condition_variable cv;
mutex mtx;
bool runt1 = true;
bool runt2 = false;
constexpr int COUNT = 3;
thread t1([&]()
{
for(int i = 0; i < COUNT; ++i)
{
unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&](){ return runt1; });
cout << "1" << endl;
runt1 = false;
runt2 = true;
lck.unlock();
cv.notify_one();
}
});
thread t2([&]()
{
for(int i = 0; i < COUNT; ++i)
{
unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&](){ return runt2; });
cout << "2" << endl;
runt1 = true;
runt2 = false;
lck.unlock();
cv.notify_one();
}
});
t1.join();
t2.join();
return 0;
}
I think you have a data race between your threads starting and the call to cv1.notify_one(); in main().
Consider the case when cv1.notify_one() call happens before thread 1 has started and called cv1.wait(). After that no one calls cv1.notify anymore and your cv-s are just waiting. This is called Lost Wake-up.
You need a mechanism to wait in main till both threads have started, then execute cv1.notify()
Below is an example using int and a mutex.
#include "pch.h"
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
condition_variable cv1, cv2;
mutex m;
const int COUNT = 3;
enum Turn
{
T1,
T2
};
int main(int argc, char** argv)
{
mutex thread_start_mutex;
int num_started_threads = 0;
Turn turn = T1;
thread t1([&]() {
{
// increase the number of started threads
unique_lock<std::mutex> lck(thread_start_mutex);
++num_started_threads;
}
for (int i = 0; i < COUNT; ++i)
{
// locked cout, unlock before calling notify
{
unique_lock<std::mutex> lck1(m);
// wait till main thread calls notify
cv1.wait(lck1, [&] { return turn == T1;});
cout << "1 a really long string" << endl;
turn = T2; // next it's T2's turn
}
cv2.notify_one();
}
});
thread t2([&]() {
{
// increase the number of started threads
unique_lock<std::mutex> lck(thread_start_mutex);
++num_started_threads;
}
for (int i = 0; i < COUNT; ++i)
{
// locked cout, unlock before calling notify
{
unique_lock<std::mutex> lck2(m);
cv2.wait(lck2, [&] {return turn == T2;});
cout << "2 some other stuff to test" << endl;
turn = T1;
}
cv1.notify_one();
}
});
unique_lock<std::mutex> lck(thread_start_mutex);
// wait until both threads have started
cv1.wait(lck, [&] { return num_started_threads == 2; });
lck.unlock();
cv1.notify_one();
t1.join();
t2.join();
return 0;
}
Also it's unclear why you have two mutexes that are locked outside of main. I usually think of a mutex as something that is protected a resource that should not be accessed concurrently. Seems like the idea was to protect the cout calls, for which you should use one mutex, that each thread will lock, do the cout, unlock and notify the other one.
Edit
My original answer had exact same issue between calls to t1.notify() and t2.wait().
If t1.notify() was called before thread 2 was waiting, thread 2 never got woken up.
To address this I added an enum "Turn" which indicates who's turn it is, and each wait condition now checks if it's their turn or not.
If it is, they are not waiting and just printing out, so even if notify was missed they'd still do their task. If it is not their turn, they'll block until the other thread sets turn variable and calls notify.
NOTE: This demonstrates a good example/practice that it's usually much better to have a condition when using cv.wait(). This both makes intentions clear, and avoids both Lost Wake-up and Spurious Wake-ups.
NOTE 2 this solution might be overly complicated, and in general condition variables and mutexes are unlikely the best approach for this problem.
The other answer is right conceptually but still has another race condition. I ran the code and it would still deadlock.
The issue is that t1 is created, but it does not get to cv1.wait(lck1) until after the cv1.notify_one() executes. Thus your two threads sit together forever waiting. You demonstrate this when you put your breakpoint on that line, allowing the thread to catch up. Also, this issue persists when one thread finishes but doesn't give the other time to call wait() so it just calls notify_one. This can be seen, also fixed* (used loosely), by adding some usleep(100) calls from unistd.h.
See below:
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <unistd.h>
using namespace std;
mutex cout_lock;
condition_variable cv1, cv2;
mutex mtx1;
unique_lock<std::mutex> lck1(mtx1);
mutex mtx2;
unique_lock<std::mutex> lck2(mtx2);
const int COUNT = 3;
int main(int argc, char** argv)
{
thread t1([&](){
for(int i = 0; i < COUNT; ++i)
{
cv1.wait(lck1);
cout << "1\n";
usleep(100);
cv2.notify_one();
}
});
thread t2([&](){
for(int i = 0; i < COUNT; ++i)
{
cv2.wait(lck2);
cout << "2\n";
usleep(100);
cv1.notify_one();
}
});
usleep(1000);
cv1.notify_one();
t1.join();
t2.join();
return 0;
}
EDIT: To do better would be to check for waiting threads, which is not built into the mutexes you use. The proper way might be to create your own mutex wrapper class and include that functionality in the class, but for simplicity sake, I just made a waiting variable.
See below:
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <unistd.h>
using namespace std;
mutex cout_lock;
condition_variable cv1, cv2, cv3;
mutex mtx1;
unique_lock<std::mutex> lck1(mtx1);
mutex mtx2;
unique_lock<std::mutex> lck2(mtx2);
int waiting = 0;
const int COUNT = 3;
int main(int argc, char** argv)
{
thread t1([&](){
for(int i = 0; i < COUNT; ++i)
{
waiting++;
cv1.wait(lck1);
cout << "1\n";
waiting--;
if(!waiting)
usleep(100);
cv2.notify_one();
}
});
thread t2([&](){
for(int i = 0; i < COUNT; ++i)
{
waiting++;
cv2.wait(lck2);
cout << "2\n";
waiting--;
if(!waiting)
usleep(100);
cv1.notify_one();
}
});
if(!waiting)
usleep(100);
cv1.notify_one();
t1.join();
t2.join();
return 0;
}
I try to write a producer-consumer demo with c++11 but a tricky problem happend.Here is the Code
#include <iostream>
#include <thread>
#include <condition_variable>
#include <windows.h>
using namespace std;
std::condition_variable pcv,ccv;
std::mutex m,m1;
const int N=10;
int buf[N];
int count=0;
void producer(){
Sleep(100);
while(true){
std::unique_lock<std::mutex> pulk(m);
while(count==N)
pcv.wait(pulk);
buf[count++]=1;
cout<<"produce data on the buff: "<<count<<endl;
while(count==1) //if I remove this no problem
ccv.notify_one();
pulk.unlock();
}
}
void consumer(){
while(true){
std::unique_lock<std::mutex> culk(m);
while(count==0)
ccv.wait(culk);
buf[--count]=0;
cout<<"consume data on the buff: "<<count<<endl;
while(count==N-1) //if I remove no problem
pcv.notify_one();
culk.unlock();
}
}
int main(int argc,char **argv){
std::thread pro(producer);
std::thread con(consumer);
pro.join();
con.join();
return 0;
the program will run the next line forever
while(count==1) //if the buffer empty?
ccv.notify_one()
I try to use GDB find this reason but no result
Here is the GDB output
The lines while(count==1) //if I remove this no problem and while(count==N-1) //if I remove no problem make your synchronization fragile. You consider only two states of ten (N) possible.
I'm investigating an issue where my worker thread deadlocks when I try to stop it.
Here's the minimal version that has the problem:
#include <atomic>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
class Worker
{
private:
std::atomic<bool> m_running;
std::condition_variable m_cond;
std::mutex m_mutex;
std::function<void()> m_workItem;
std::thread m_thread;
public:
Worker() :
m_running(true),
m_thread(std::bind(&Worker::DoWork, this))
{
}
~Worker()
{
Stop();
m_thread.join();
}
bool QueueWork(std::function<void()> item)
{
std::unique_lock<std::mutex> padlock(m_mutex);
if (m_workItem)
{
return false;
}
m_workItem = item;
padlock.unlock();
m_cond.notify_all();
return true;
}
void Stop()
{
bool expected = true;
if (m_running.compare_exchange_strong(expected, false))
{
m_cond.notify_all();
}
}
private:
void DoWork() noexcept
{
while (m_running)
{
std::unique_lock<std::mutex> padlock(m_mutex);
m_cond.wait(padlock,
[this]
()
{
return !m_running || m_workItem;
});
if (m_workItem)
{
decltype(m_workItem) workItem;
std::swap(m_workItem, workItem);
padlock.unlock();
workItem();
}
}
}
};
int main()
{
std::cout << "Start." << std::endl;
{
std::vector<std::unique_ptr<Worker>> workers;
for (int i = 0; i < 10; ++i)
{
workers.push_back(std::unique_ptr<Worker>(new Worker()));
}
workers[0]->QueueWork(
[]()
{
std::cout << "Work item" << std::endl;
});
std::this_thread::sleep_for(std::chrono::milliseconds(10));
for (auto & worker : workers)
{
worker->Stop();
}
for (auto & worker : workers)
{
worker.reset();
}
}
std::cout << "Stop." << std::endl;
return 0;
}
The idea is that when calling Worker::Stop() from the host thread, Worker::m_running is set to false, and notify_all() is called on Worker::m_cond. The worker thread wakes up from its m_cond.wait(), checks m_running and breaks out, exiting the thread function.
Sometimes, however, this deadlocks. The worker thread wakes up, sees that m_running is true (how is that possible?) and goes back to wait(). There's no additional call to m_cond.notify_all() so the thread ends up in a deadlocked state.
I spawn 10 Worker objects in this code. I don't think it has anything to do with the number of threads, but to be able to trigger the race condition (if that's what it is), I needed more threads.
What is wrong with the code?
Running gcc:
g++ --version
g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Compiling using:
g++ -std=c++11 -pedantic test.cpp -lpthread
Edit:
Changed the order of Worker's private members. m_thread is now last. Still the same problem.
I have implemented a sample program to understand how wait_for and wait_until works in C++11.
Code -
#include <iostream>
#include <future>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <thread>
using namespace std;
using namespace std::chrono;
condition_variable cv;
mutex m;
bool flagValue=false;
int sampleFunction(int a)
{
cout<<"Executing sampleFunction...";
cout.flush();
this_thread::sleep_for(seconds(5));
cout<<"Done."<<endl;
return a;
}
void sampleFunctionCond(int a)
{
lock_guard<mutex> lg(m);
cout<<"Executing sampleFunctionCond...";
cout.flush();
this_thread::sleep_for(seconds(5));
cout<<"Done."<<endl;
cout<<"Value : "<<a<<endl;
flagValue=true;
cv.notify_one();
return;
}
int main()
{
unique_lock<mutex> ul(m);
future<int> f1=async(launch::async,sampleFunction,10);
future_status statusF1=f1.wait_for(seconds(1));
if(statusF1==future_status::ready)
cout<<"Future is ready"<<endl;
else if (statusF1==future_status::timeout)
cout<<"Timeout occurred"<<endl;
else if (statusF1==future_status::deferred)
cout<<"Task is deferred"<<endl;
cout<<"Value : "<<f1.get()<<endl;
cv_status statusF2;
thread t1(sampleFunctionCond,20);
t1.detach();
while(!flagValue)
{
statusF2=cv.wait_until(ul,system_clock::now()+seconds(2));
if(statusF2==cv_status::timeout)
{
cout<<"Timeout occurred."<<endl;
break;
}
else
{
cout<<"Condition variable is ready or spurious wake up occurred."<<endl;
}
}
}
Output -
Executing sampleFunction...Timeout occurred
Done.
Value : 10
Executing sampleFunctionCond...Done.
Value : 20
Timeout occurred.
sampleFunction is working as expected as its printing "Timeout occurred" before "Done" but same is not the case with sampleFunctionCond. Though it knows wait_until has timed out but its printing the message after the function sampleFunctionCOnd has finished executing.
Can someone please help me understand this? Thanks.
There is a race condition in statusF2=cv.wait_until(...); statement. What may happen is that the wait has timed out and is about to return. To return it needs to reacquire the mutex. At the same time the other thread has acquired the mutex. So, statusF2=cv.wait_until(...); can't return till the other thread has set flagValue to true and released the mutex.
To fix the code the value of flagValue must be checked before checking whether the wait timed out.
The function "sampleFunctionCond" should not hold the mutex "m" all time. You can try to lock "m" immediately before the line "flagValue=true;".