Considering the following, simple code:
using ms = std::chrono::milliseconds;
int val = 0;
for(;;)
{
std::cout << val++ << ' ';
std::this_thread::sleep_for(ms(200));
}
We see that we infinitely print subsequent numbers each 0.2 second.
Now, I would like to implement the same logic using a helper class and multithreading. My aim is to be able to run something similar to this:
int main()
{
Foo f;
std::thread t1(&Foo::inc, f);
std::thread t2(&Foo::dis, f);
t1.join();
t2.join();
}
where Foo::inc() will increment a member variable val of an object f by 1 and Foo::dis() will display the same variable.
Since the original idea consisted of incrementing and printing the value infinitely, I would assume that both of those functions must contain an infinite loop. The problem that could occur is data race - reading and incrementing the very same variable. To prevent that I decided to use std::mutex.
My idea of implementing Foo is as follows:
class Foo {
int val;
public:
Foo() : val{0} {}
void inc()
{
for(;;){
mtx.lock();
++val;
mtx.unlock();
}
}
void dis()
{
using ms = std::chrono::milliseconds;
for(;;){
mtx.lock();
std::cout << val << ' ';
std::this_thread::sleep_for(ms(200));
mtx.unlock();
}
}
};
Obviously it's missing the mtx object, so the line
std::mutex mtx;
is written just under the #includes, declaring mtx as a global variable.
To my understanding, combining this class' definition with the above main() function should issue two, separate, infinite loops that each will firstly lock the mutex, either increment or display val and unlock the mutex so the other one could perform the second action.
What actually happens is instead of displaying the sequence of 0 1 2 3 4... it simply displays 0 0 0 0 0.... My guess is that I am either using std::mutex::lock and std::mutex::unlock incorrectly, or my fundamental understanding of multithreading is lacking some basic knowledge.
The question is - where is my logic wrong?
How would I approach this problem using a helper class and two std::threads with member functions of the same object?
Is there a guarantee that the incrementation of val and printing of it will each occur one after the other using this kind of logic? i.e. will there never be a situation when val is incremented twice before it being displayed, or vice versa?
You are sleeping with the thread locked preventing the other thread from running for most of the time.
void dis()
{
using ms = std::chrono::milliseconds;
for(;;){
mtx.lock();
std::cout << val << ' ';
std::this_thread::sleep_for(ms(200)); // this is still blocking the other thread
mtx.unlock();
}
}
Try this:
void dis()
{
using ms = std::chrono::milliseconds;
for(;;){
mtx.lock();
std::cout << val << ' ';
mtx.unlock(); // unlock to allow the other thread to progress
std::this_thread::sleep_for(ms(200));
}
}
Also, rather than using a global std::mutex you could add it as a member of your class.
If you want to synchronize the threads to produce an even output of numbers incrementing by exactly one each time then you need something like a std::condition_variable so that each thread can signal the other when it has done it's part of the job (thread one - incrementing and thread 2 - printing).
Here is an example:
class Foo {
int val;
std::mutex mtx;
std::condition_variable cv;
bool new_value; // flag when a new value is ready
public:
Foo() : val{0}, new_value{false} {}
void inc()
{
for(;;){
std::unique_lock<std::mutex> lock(mtx);
// release the lock and wait until new_value has been consumed
cv.wait(lock, [this]{ return !new_value; }); // wait for change in new_value
++val;
new_value = true; // signal for the other thread there is a new value
cv.notify_one(); // wake up the other thread
}
}
void dis()
{
using ms = std::chrono::milliseconds;
for(;;){
// a nice delay
std::this_thread::sleep_for(ms(200));
std::unique_lock<std::mutex> lock(mtx);
// release the lock and wait until new_value has been produced
cv.wait(lock, [this]{ return new_value; }); // wait for a new value
std::cout << val << ' ' << std::flush; // don't forget to flush
new_value = false; // signal for the other thread that the new value was used
cv.notify_one(); // wake up the other thread
}
}
};
int main(int argc, char** argv)
{
Foo f;
std::thread t1(&Foo::inc, &f);
std::thread t2(&Foo::dis, &f);
t1.join();
t2.join();
}
A mutex is not a signal. It is not fair. You can unlock then relock a mutex, and someone waiting for it can never notice.
All it guarantees is that exactly one thread has it locked.
Your task, splitting it into two threads, seems utterly pointless. Using sleep for is also a bad idea, as printing takes an unknown amount of time, making the period between displays drift by an unpredictable amount.
You probably (A) do not want to do this, and failing that (B) use a condition variable. One thread increments the value every X time (based off a fixed start time, not based off delays of X), and then signs the condition variable. It holds no mutex while waiting.
The other thread waits on the condition variable and the counter value changing. When it wakes, it copies the counter, unlocks, prints once, updates the last value seen, then waits on the condition variable (and value changing) again.
A mild benefit to this is that if the io is ridiculously slow or blocking, the counter keeps incrementing, so other consumers can use it.
struct Counting {
int val = -1; // optionally atomic
std::mutex mtx;
std::condition_variable cv;
void counting() {
while(true){
{
auto l=std::unique_lock<std::mutex>(mtx);
++val; // even if atomic, val must be modified while or before the mtx is held and before the notify.
}
// or notify all:
cv.notify_one(); // no need to hold lock here
using namespace std::literals;
std::this_thread::sleep_for(200ms); // ideally wait to an absolute time instead of delay here
}
}
void printing() {
int old_val=-1;
while(true){
int new_val=[&]{
auto lock=std::unique_lock<std::mutex>(mtx);
cv.wait(lock, [&]{ return val!=old_val; }); // only print if we have a new value
return val;
}();// release lock, no need to hold it while printing
std::cout << new_val << std::endl; // endl flushes. Note there are threading issues streaming to cout like this.
old_val=new_val; // update last printed value
}
}
};
if one thread is printing the other counting, you'll get basically what you want.
When launching a thread with a member function, you need to pass the address of the object, not the object itself
std::thread t2(&Foo::dis, &f);
Please note that this still won't print 1 2 3 4 .. You'll need to have the increment operation and the print alternate exactly for that.
#include <thread>
#include<iostream>
#include <mutex>
std::mutex mtx1, mtx2;
class Foo {
int val;
public:
Foo() : val{0} { mtx2.lock(); }
void inc()
{
for(;;){
mtx1.lock();
++val;
mtx2.unlock();
}
}
void dis()
{
using ms = std::chrono::milliseconds;
for(;;){
mtx2.lock();
std::cout << val <<std::endl;
std::this_thread::sleep_for(ms(200));
mtx1.unlock();
}
}
};
int main()
{
Foo f;
std::thread t1(&Foo::inc, &f);
std::thread t2(&Foo::dis, &f);
t1.join();
t2.join();
}
Also take a look at http://en.cppreference.com/w/cpp/thread/condition_variable
Related
Lets say I have Object A and Object B. ObjA creates multiple 'ObjB's and keeps a pointer to each, then detaches a thread on each object B to do work. I want to implement a barrier in ObjA that only unlocks whenever all 'ObjB's have reached a certain internal condition within their work functions.
How can I create a barrier with a dynamic count within ObjA, and then make ObjB aware of that barrier so that it can arrive at the barrier? I wanted to use std::barrier but I've had problems trying to do so.
Thus far I cannot make a std::barrier member variable in ObjA because it requires an input size which I will only know once ObjA is constructed. If I create the barrier inside of the busy function of ObjA, then any signal function that ObjB calls to A with won't have scope to it.
Is the best approach to do some homespun semaphore with busy waiting?
You can use a conditional variable.
#include <iostream>
#include <condition_variable>
#include <thread>
#include <vector>
std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
// 1) to synchronize accesses to count
// 3) for the condition variable cv
int total_count = 10; // This is count of objBs
int count = total_count;
void obj_b_signals()
{
// Do something..
bool certainCondition = true;
// We have reached the condition..
if (certainCondition) {
{
std::lock_guard<std::mutex> lk(cv_m);
count--;
}
std::cerr << "Notifying...\n";
cv.notify_one();
}
}
int main()
{
// obj A logic
std::vector<std::thread> threads;
for (size_t i=0; i<total_count; ++i) {
threads.emplace_back(std::thread(obj_b_signals));
}
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting for ObjBs to reach a certain condition... \n";
cv.wait(lk, []{return count == 0;});
std::cerr << "...finished waiting. count == 0\n";
}
// Do something else
for (std::thread & t: threads) {
t.join();
}
}
I'm trying to unit test an atomic library (I am aware that an atomic library is not suitable for unit testing, but I still want to give it a try)
For this, I want to let X parallel threads increment a counter and evaluate the resulting value (it should be X).
The code is below. The problem is that is it never breaks. The Counter always nicely ends up being 2000 (see below). What I also notice is that the cout is also printed as a whole (instead of being mingled, what I remember seeing with other multithreaded couts)
My question is: why doesn't this break? Or how can I let this break?
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool start = false;
int Counter = 0;
void Inc() {
// Wait until test says start
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] {return start; });
std::cout << "Incrementing in thread " << std::this_thread::get_id() << std::endl;
Counter++;
}
int main()
{
std::vector<std::thread> threads;
for (int i = 0; i < 2000; ++i) {
threads.push_back(std::thread(Inc));
}
// signal the threads to start
{
std::lock_guard<std::mutex> lk(m);
start = true;
}
cv.notify_all();
for (auto& thread : threads) {
thread.join();
}
// Now check whether value is right
std::cout << "Counter: " << Counter << std::endl;
}
The results looks like this (but then 2000 lines)
Incrementing in thread 130960
Incrementing in thread 130948
Incrementing in thread 130944
Incrementing in thread 130932
Incrementing in thread 130928
Incrementing in thread 130916
Incrementing in thread 130912
Incrementing in thread 130900
Incrementing in thread 130896
Counter: 2000
Any help would be appreciated
UPDATE: Reducing the nr of threads to 4, but incrementing a million times in a for loop (as suggested by #tkausl) the cout of thread id appear to be sequential..
UPDATE2: Turns out that the lock had to be unlocked to prevent exclusive access per thread (lk.unlock()). An additional yield in the for-loop increased the race condition effect.
cv.wait(lk, [] {return start; }); only returns with the lk acquired. So it's exclusive. You might want to unlock lk right after:
void Inc() {
// Wait until test says start
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] {return start; });
lk.unlock();
Counter++;
}
And you must remove std::cout, because it potentially introduces synchronization.
I have two questions.
1) I want to launch some function with an infinite loop to work like a server and checking for messages in a separate thread. However I want to close it from the parent thread when I want. I'm confusing how to std::future or std::condition_variable in this case. Or is it better to create some global variable and change it to true/false from the parent thread.
2) I'd like to have something like this. Why this one example crashes during the run time?
#include <iostream>
#include <chrono>
#include <thread>
#include <future>
std::mutex mu;
bool stopServer = false;
bool serverFunction()
{
while (true)
{
// checking for messages...
// processing messages
std::this_thread::sleep_for(std::chrono::seconds(1));
mu.lock();
if (stopServer)
break;
mu.unlock();
}
std::cout << "Exiting func..." << std::endl;
return true;
}
int main()
{
std::thread serverThread(serverFunction);
// some stuff
system("pause");
mu.lock();
stopServer = true;
mu.unlock();
serverThread.join();
}
Why this one example crashes during the run time?
When you leave the inner loop of your thread, you leave the mutex locked, so the parent thread may be blocked forever if you use that mutex again.
You should use std::unique_lock or something similar to avoid problems like that.
You leave your mutex locked. Don't lock mutexes manually in 999/1000 cases.
In this case, you can use std::unique_lock<std::mutex> to create a RAII lock-holder that will avoid this problem. Simply create it in a scope, and have the lock area end at the end of the scope.
{
std::unique_lock<std::mutex> lock(mu);
stopServer = true;
}
in main and
{
std::unique_lock<std::mutex> lock(mu);
if (stopServer)
break;
}
in serverFunction.
Now in this case your mutex is pointless. Remove it. Replace bool stopServer with std::atomic<bool> stopServer, and remove all references to mutex and mu from your code.
An atomic variable can safely be read/written to from different threads.
However, your code is still busy-waiting. The right way to handle a server processing messages is a condition variable guarding the message queue. You then stop it by front-queuing a stop server message (or a flag) in the message queue.
This results in a server thread that doesn't wake up and pointlessly spin nearly as often. Instead, it blocks on the condition variable (with some spurious wakeups, but rare) and only really wakes up when there are new messages or it is told to shut down.
template<class T>
struct cross_thread_queue {
void push( T t ) {
{
auto l = lock();
data.push_back(std::move(t));
}
cv.notify_one();
}
boost::optional<T> pop() {
auto l = lock();
cv.wait( l, [&]{ return halt || !data.empty(); } );
if (halt) return {};
T r = data.front();
data.pop_front();
return std::move(r); // returning to optional<T>, so we'll explicitly `move` here.
}
void terminate() {
{
auto l = lock();
data.clear();
halt = true;
}
cv.notify_all();
}
private:
std::mutex m;
std::unique_lock<std::mutex> lock() {
return std::unique_lock<std::mutex>(m);
}
bool halt = false;
std::deque<T> data;
std::condition_variable cv;
};
We use boost::optional for the return type of pop -- if the queue is halted, pop returns an empty optional. Otherwise, it blocks until there is data.
You can replace this with anything optional-like, even a std::pair<bool, T> where the first element says if there is anything to return, or a std::unique_ptr<T>, or a std::experimental::optional, or a myriad of other choices.
cross_thread_queue<int> queue;
bool serverFunction()
{
while (auto message = queue.pop()) {
// processing *message
std::cout << "Processing " << *message << std::endl;
}
std::cout << "Exiting func..." << std::endl;
return true;
}
int main()
{
std::thread serverThread(serverFunction);
// some stuff
queue.push(42);
system("pause");
queue.terminate();
serverThread.join();
}
live example.
So I have two threads where they share the same variable, 'counter'. I want to synchronize my threads by only continuing execution once both threads have reached that point. Unfortunately I enter a deadlock state as my thread isn't changing it's checking variable. The way I have it is:
volatile int counter = 0;
Thread() {
- some calculations -
counter++;
while(counter != 2) {
std::this_thread::yield();
}
counter = 0;
- rest of the calculations -
}
The idea is that since I have 2 threads, once they reach that point - at different times - they will increment the counter. If the counter isn't equal to 2, then the thread that reached there first will have to wait until the other has incremented the counter so that they are synced up. Does anyone know where the issue lies here?
To add more information about the problem, I have two threads which perform half of the operations on an array. Once they are done, I want to make sure that they both have completed finish their calculations. Once they are, I can signal the printer thread to wake up and perform it's operation of printing and clearing the array. If I do this before both threads have completed, there will be issues.
Pseudo code:
Thread() {
getLock()
1/2 of the calculations on array
releaseLock()
wait for both to finish - this is the issue
wake up printer thread
}
In situations like this, you must use an atomic counter.
std::atomic_uint counter = 0;
In the given example, there is also no sign that counter got initialized.
You are probably looking for std::conditional_variable: A conditional variable allows one thread to signal to another thread. Because it doesn't look like you are using the counter, and you're only using it for synchronisation, here is some code from another answer (disclaimer: it's one of my answers) that shows std::conditional_variable processing logic on different threads, and performing synchronisation around a value:
unsigned int accountAmount;
std::mutex mx;
std::condition_variable cv;
void depositMoney()
{
// go to the bank etc...
// wait in line...
{
std::unique_lock<std::mutex> lock(mx);
std::cout << "Depositing money" << std::endl;
accountAmount += 5000;
}
// Notify others we're finished
cv.notify_all();
}
void withdrawMoney()
{
std::unique_lock<std::mutex> lock(mx);
// Wait until we know the money is there
cv.wait(lock);
std::cout << "Withdrawing money" << std::endl;
accountAmount -= 2000;
}
int main()
{
accountAmount = 0;
// Run both threads simultaneously:
std::thread deposit(&depositMoney);
std::thread withdraw(&withdrawMoney);
// Wait for both threads to finish
deposit.join();
withdraw.join();
std::cout << "All transactions processed. Final amount: " << accountAmount << std::endl;
return 0;
}
I would look into using a countdown latch. The idea is to have one or more threads block until the desired operation is completed. In this case you want to wait until both threads are finished modifying the array.
Here is a simple example:
#include <condition_variable>
#include <mutex>
#include <thread>
class countdown_latch
{
public:
countdown_latch(int count)
: count_(count)
{
}
void wait()
{
std::unique_lock<std::mutex> lock(mutex_);
while (count_ > 0)
condition_variable_.wait(lock);
}
void countdown()
{
std::lock_guard<std::mutex> lock(mutex_);
--count_;
if (count_ == 0)
condition_variable_.notify_all();
}
private:
int count_;
std::mutex mutex_;
std::condition_variable condition_variable_;
};
and usage would look like this
std::atomic<int> result = 0;
countdown_latch latch(2);
void perform_work()
{
++result;
latch.countdown();
}
int main()
{
std::thread t1(perform_work);
std::thread t2(perform_work);
latch.wait();
std::cout << "result = " << result;
t1.join();
t2.join();
}
I am relatively new to threads, and I'm still learning best techniques and the C++11 thread library. Right now I'm in the middle of implementing a worker thread which infinitely loops, performing some work. Ideally, the main thread would want to stop the loop from time to time to sync with the information that the worker thread is producing, and then start it again. My idea initially was this:
// Code run by worker thread
void thread() {
while(run_) {
// Do lots of work
}
}
// Code run by main thread
void start() {
if ( run_ ) return;
run_ = true;
// Start thread
}
void stop() {
if ( !run_ ) return;
run_ = false;
// Join thread
}
// Somewhere else
volatile bool run_ = false;
I was not completely sure about this so I started researching, and I discovered that volatile is actually not required for synchronization and is in fact generally harmful. Also, I discovered this answer, which describes a process nearly identical to the one I though about. In the answer's comments however, this solution is described as broken, as volatile does not guarantee that different processor cores readily (if ever) communicate changes on the volatile values.
My question is this then: Should I use an atomic flag, or something else entirely? What exactly is the property that is lacking in volatile and that is then provided by whatever construct is needed to solve my problem effectively?
Have you looked for the Mutex ? They're made to lock the Threads avoiding conflicts on the shared data. Is it what you're looking for ?
I think you want to use barrier synchronization using std::mutex?
Also take a look at boost thread, for a relatively high level threading library
Take a look at this code sample from the link:
#include <iostream>
#include <map>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
std::map<std::string, std::string> g_pages;
std::mutex g_pages_mutex;
void save_page(const std::string &url)
{
// simulate a long page fetch
std::this_thread::sleep_for(std::chrono::seconds(2));
std::string result = "fake content";
g_pages_mutex.lock();
g_pages[url] = result;
g_pages_mutex.unlock();
}
int main()
{
std::thread t1(save_page, "http://foo");
std::thread t2(save_page, "http://bar");
t1.join();
t2.join();
g_pages_mutex.lock(); // not necessary as the threads are joined, but good style
for (const auto &pair : g_pages) {
std::cout << pair.first << " => " << pair.second << '\n';
}
g_pages_mutex.unlock();
}
I would suggest to use std::mutex and std::condition_variable to solve the problem. Here's an example how it can work with C++11:
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
int main()
{
mutex m;
condition_variable cv;
// Tells, if the worker should stop its work
bool done = false;
// Zero means, it can be filled by the worker thread.
// Non-zero means, it can be consumed by the main thread.
int result = 0;
// run worker thread
auto t = thread{ [&]{
auto bound = 1000;
for (;;) // ever
{
auto sum = 0;
for ( auto i = 0; i != bound; ++i )
sum += i;
++bound;
auto lock = unique_lock<mutex>( m );
// wait until we can safely write the result
cv.wait( lock, [&]{ return result == 0; });
// write the result
result = sum;
// wake up the consuming thread
cv.notify_one();
// exit the loop, if flag is set. This must be
// done with mutex protection. Hence this is not
// in the for-condition expression.
if ( done )
break;
}
} };
// the main threads loop
for ( auto i = 0; i != 20; ++i )
{
auto r = 0;
{
// lock the mutex
auto lock = unique_lock<mutex>( m );
// wait until we can safely read the result
cv.wait( lock, [&]{ return result != 0; } );
// read the result
r = result;
// set result to zero so the worker can
// continue to produce new results.
result = 0;
// wake up the producer
cv.notify_one();
// the lock is released here (the end of the scope)
}
// do time consuming io at the side.
cout << r << endl;
}
// tell the worker to stop
{
auto lock = unique_lock<mutex>( m );
result = 0;
done = true;
// again the lock is released here
}
// wait for the worker to finish.
t.join();
cout << "Finished." << endl;
}
You could do the same with std::atomics by essentially implementing spin locks. Spin locks can be slower than mutexes. So I repeat the advise on the boost website:
Do not use spinlocks unless you are certain that you understand the consequences.
I believe that mutexes and condition variables are the way to go in your case.