C++ multi thread programming with timer - c++

I am new to multi thread programming, so this question might seem a little silly, but I really need to work this out so I can apply it to my project (which is way more complicated).
Follow is my code, I am trying to have 2 threads (parent and child) to update the same shared timer as they execute and stop when the timer reaches a specific limit.
But when I compile and execute this follow piece of code, there are 2 different outcomes: 1. child prints "done by child at 200000" but the program does not exit; 2. after child prints "done by child at 200000" and exits, parent keeps executing, prints a couple of dozen lines of "parent doing work" and "parent at 190000", then prints "done by parent at 200000" and the program exits properly.
The behavior I want is for whichever thread that updates the timer, hits the limit and exits, the other thread should stop executing and exit as well. I think I might be missing something trivial here, but I've tried changing the code in many ways and nothing I tried seem to work. Any help will be much appreciated :)
#include <iostream>
#include <unistd.h>
#include <mutex>
#include <time.h>
using namespace std;
mutex mtx;
int main () {
int rc;
volatile int done = 0;
clock_t start = clock();
volatile clock_t now;
rc = fork();
if (rc == 0) { //child
while (true) {
cout << "child doing work" << endl;
mtx.lock();
now = clock() - start;
if (done) {
mtx.unlock();
break;
}
if (now >= 200000 && !done) {
done = 1;
cout << "done by child at " << now << endl;
mtx.unlock();
break;
}
cout << "child at " << now << endl;
mtx.unlock();
}
_exit(0);
}
else { // parent
while (true) {
cout << "parent doing work" << endl;
mtx.lock();
now = clock() - start;
if (done) {
mtx.unlock();
break;
}
if (now >= 200000 && !done) {
done = 1;
cout << "done by parent at " << now << endl;
mtx.unlock();
break;
}
cout << "parent at " << now << endl;
mtx.unlock();
}
}
return 0;
}

Multi-processes
Your code is multi-processes and not multi-threading: fork() will create a new separate process by duplicating the calling process.
The consequence: At the moment of the duplication, all the variables contain the same value in both processes. But each process has its own copy, so a variable modified in the parent will not be updated in the child's address space an vice-versa.
If you want to share variables between processes, you should have a look at this SO question
Multithread
For real multithreading, you should use std::thread. And forget about volatile, because it's not thread safe. Use <atomic> instead, as explained in this awesome video.
Here a first try:
#include <iostream>
#include <mutex>
#include <thread>
#include <atomic>
#include <time.h>
using namespace std;
void child (atomic<int>& done, atomic<clock_t>& now, clock_t start)
{
while (!done) {
cout << "child doing work" << endl;
now = clock() - start;
if (now >= 2000 && !done) {
done = 1;
cout << "done by child at " << now << endl;
}
cout << "child at " << now << endl;
this_thread::yield();
}
}
void parent (atomic<int>& done, atomic<clock_t>& now, clock_t start)
{
while (!done) {
cout << "parent doing work" << endl;
now = clock() - start;
if (now >= 2000 && !done) {
done = 1;
cout << "done by parent at " << now << endl;
}
cout << "parent at " << now << endl;
this_thread::yield();
}
}
int main () {
atomic<int> done{0};
clock_t start = clock();
atomic<clock_t> now;
thread t(child, std::ref(done), std::ref(now), start); // attention, without ref, you get clones
parent (done, now, start);
t.join();
return 0;
}
Note that you don't need to protect atomic accesses with a mutex, and that if you want to do, lock_guard would be recommended alternative.
This example is of course rather weak, because if you test an atomic variable if the if-condition, it's value might already have changed when entering the if-block. This doesn't cause a problem in your logic where "done" means "done". But if you'd need a more cauthious approach,
compare_exchange_weak() or compare_exchange_strong() could help further.

Related

How to correctly pause and resume a std::thread?

I'm new to multithreading in C++. I just want to define a class TaskManager that allows me to handle the execution of a general task. The core logic of the task should be implemented in the task() method. Then I want to implement the start(), pause(), and resume() methods to handle the execution of task(). Is there any problem with this implementation? Is it the right way to handle this kind of problem? is there a way to abstract the core logic from the task() method?
#include <iostream>
#include <thread>
#include <chrono>
class TaskManager{
private:
std::condition_variable cv;
std::mutex mtx;
std::thread task_thread;
bool paused = true;
bool finished = false;
int counter = 0;
int MAX_COUNT = INT_MAX;
public:
~TaskManager(){
if (this->task_thread.joinable()){
this->task_thread.join();
}
}
void task(){
// Finishing condition. ==> counter < this->MAX_COUNT
while(counter < this->MAX_COUNT){
std::unique_lock<std::mutex> ul(this->mtx);
this->cv.wait(ul, [this] {return (!this->paused);});
// CORE LOGIC...
counter++;
}
std::cout << "Finished!" << std::endl;
this->finished = true;
}
void start(){
std::unique_lock<std::mutex> ul(this->mtx);
this->paused = false;
task_thread = std::thread([this]{this->task();});
cv.notify_one();
}
void pause(){
std::unique_lock<std::mutex> ul(this->mtx);
if (!this->finished) {
this->paused = true;
this->cv.notify_one();
}
}
void resume(){
std::unique_lock<std::mutex> ul(this->mtx);
if (!this->finished) {
this->paused = false;
this->cv.notify_one();
}
}
int getCounter() {
return this->counter;
}
};
int main() {
TaskManager tm;
std::cout << "counter before start(): " << tm.getCounter() << std::endl;
tm.start();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "counter after 10 ms: " << tm.getCounter() << std::endl;
tm.pause();
std::cout << "counter after pause(): " << tm.getCounter() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "counter after 10 ms: " << tm.getCounter() << std::endl;
tm.resume();
std::cout << "counter after resume(): " << tm.getCounter() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "counter after 10 ms: " << tm.getCounter() << std::endl;
return 0;
}
Output:
counter before start(): 0
counter after 10 ms: 266967
counter after pause(): 267526
counter after 10 ms: 267526
counter after resume(): 267526
counter after 10 ms: 487041
Finished!
Is there any problem with this implementation?
There's data race on counter
You probably don't want to hold the lock while executing // CORE LOGIC.... If you mean to protect counter, you should prefer another mutex for it.
finished should be under the lock too. Alternatively, it could be atomic. Note that unnecessary notifications don't hurt, so you can sip finished altogether
Is it the right way to handle this kind of problem?
Depending on why do you want to pause in the first place. For some reasons to pause there could be a better approach, like C++20 latch/semaphore/barrier.
is there a way to abstract the core logic from the task() method?
To what extent. You can change it to
void CoreLogic(std::function<void()> pause_callback) {
pause_callback();
// Core logic
}
You cannot pause a thread in an arbitrary point with C++ facilities. Maybe you can with platform facilities (like, Windows has SuspendThread), but it may not be a good idea (imagine a thread acquires malloc internal lock when paused).

Threads in C++ The interleaving pattern

In this program, I'm trying to print my username and then create two threads. I want each thread to print its thread id and go into a loop and display something periodically.
Here is the code I have
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <string>
void task(std::string threadNum)
{
std::thread::id this_id = std::this_thread::get_id();
std::cout << threadNum << " : " << this_id << std::endl;
for(int i=0; i<1000; i++){
if(i == 300 or i == 600 or i == 900){
std::cout << threadNum << " has reached step: " << i << std::endl;
}
}
}
int main()
{
std::cout << "Your Username Is: " << getenv("USER") << std::endl;
std::thread t1(task, "Thread 1");
std::thread t2(task, "Thread 2");
t1.join();
t2.join();
}
and I get different outputs every single time I run the program, for example
Your Username Is: gansaikhanshur
Thread 2 : Thread 1 : 0x70000741e000
Thread 2 has reached step: 0x70000739b000300
Thread 1 has reached step: 300
Thread 2 has reached step: 600
Thread 2 has reached step: 900
Thread 1 has reached step: 600
Thread 1 has reached step: 900
Thread1 and Thread 2 does not show it's thread ID as it should. Why do I get different results all the time? and Is it possible for me to make thread 1 and thread 2 to display their correct thread ids?
This is the way threads work -- they run independently and any side-effects they have may show up interleaved in any order. If you want to ensure that doesn't happen, you need to synchronize. For example, if you want to ensure that lines written to cout don't get mixed up, you can lock around each line output:
std::mutex cout_lock;
void task(std::string threadNum)
{
std::thread::id this_id = std::this_thread::get_id();
{
std::lock_guard<std::mutex> lock(cout_lock);
std::cout << threadNum << " : " << this_id << std::endl;
}
for(int i=0; i<1000; i++){
if(i == 300 or i == 600 or i == 900) {
std::lock_guard<std::mutex> lock(cout_lock);
std::cout << threadNum << " has reached step: " << i << std::endl;
}
}
}
lock_guard gives you a nice easy exception-safe way to manage lock/unlock operations.

Condition Variable with a while loop in thread in C++

I'm trying to figure out how to use std::condition_variable in C++ implementing a "strange" producer and consumer program in which I had set a limit to the count variable.
The main thread ("producer") increments the count and must wait for this to return to zero to issue a new increment.
The other threads enters in a loop where they have to decrease the counter and issue the notification.
I am blocked because it is not clear to me how to conclude the program by orderly exiting the while loop inside the function of all threads.
Could someone give me some guidance on how to implement it, please?
Code
#include <iostream>
#include <thread>
#include <condition_variable>
#include <vector>
int main() {
int n_core = std::thread::hardware_concurrency();
std::vector<std::thread> workers;
int max = 100;
int count = 0;
std::condition_variable cv;
std::mutex mutex;
int timecalled = 0;
for (int i = 0; i < n_core; i++) {
workers.emplace_back(std::thread{[&max, &count, &mutex, &cv]() {
while (true) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 1; });
std::cout << std::this_thread::get_id() << " - " << count << std::endl;
count--;
std::cout << std::this_thread::get_id() << " notify dec" << std::endl;
cv.notify_all();
}
}});
}
while (max > 0) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 0; });
std::cout << std::this_thread::get_id() << " created token" << std::endl;
count++;
max--;
timecalled++;
std::cout << std::this_thread::get_id() << " notify inc" << std::endl;
cv.notify_all();
}
for (auto &w : workers) {
w.join();
}
std::cout << timecalled << std::endl; // must be equal to max
std::cout << count << std::endl; // must be zero
}
Problem
The program doesn't end because it is stuck on some final join.
Expected Result
The expected result must be:
100
0
Edits Made
EDIT 1 : I replaced max > 0 in the while with a true. Now the loops are unbounded, but using the solution of #prog-fh seems to work.
EDIT 2 : I added a variable to check the result in the end.
EDIT 3: I changed while(true) to while(max >0). Could this be a problem in concurrency because we are reading it without a lock?
The threads are waiting for something new in the call cv.wait().
But the only change that can be observed with the provided lambda-closure is the value of count.
The value of max must be checked too in order to have a chance to leave this cv.wait() call.
A minimal change in your code could be
cv.wait(lk, [&max, &count]() { return count == 1 || max<=0; });
if(max<=0) break;
assuming that changes to max always occur under the control of the mutex.
An edit to clarify around the accesses to max.
If the loop run by the threads is now while(true), then the max variable is only read in its body which is synchronised by mutex (thanks to lk).
The loop run by the main program is while (max > 0): max is read without synchronisation here but the only thread that can change this variable is the main program itself, so it's pure serial code from this perspective.
The whole body of this loop is synchronised by mutex (thanks to lk) so it is safe to change the value of max here since the read operations in the threads are synchronised in the same way.
You're having race conditions: in your code max may be read by multiple threads, whilst it is being modified in main, which is a race condition according to C++ standard.
The predicates you are using in wait seems to be incorrect (you're using ==).

How can I execute two threads asynchronously using boost?

I have the book "beyond the C++ standard library" and there are no examples of multithreading using boost. Would somebody be kind enough to show me a simple example where two threads are executed using boost- lets say asynchronously?
This is my minimal Boost threading example.
#include <boost/thread.hpp>
#include <iostream>
using namespace std;
void ThreadFunction()
{
int counter = 0;
for(;;)
{
cout << "thread iteration " << ++counter << " Press Enter to stop" << endl;
try
{
// Sleep and check for interrupt.
// To check for interrupt without sleep,
// use boost::this_thread::interruption_point()
// which also throws boost::thread_interrupted
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
catch(boost::thread_interrupted&)
{
cout << "Thread is stopped" << endl;
return;
}
}
}
int main()
{
// Start thread
boost::thread t(&ThreadFunction);
// Wait for Enter
char ch;
cin.get(ch);
// Ask thread to stop
t.interrupt();
// Join - wait when thread actually exits
t.join();
cout << "main: thread ended" << endl;
return 0;
}

Still having race condition with boost::mutex

I am trying an example, which causes race condition to apply the mutex. However, even with the mutex, it still happens. What's wrong? Here is my code:
#include <iostream>
#include <boost/thread.hpp>
#include <vector>
using namespace std;
class Soldier
{
private:
boost::thread m_Thread;
public:
static int count , moneySpent;
static boost::mutex soldierMutex;
Soldier(){}
void start(int cost)
{
m_Thread = boost::thread(&Soldier::process, this,cost);
}
void process(int cost)
{
{
boost::mutex::scoped_lock lock(soldierMutex);
//soldierMutex.lock();
int tmp = count;
++tmp;
count = tmp;
tmp = moneySpent;
tmp += cost;
moneySpent = tmp;
// soldierMutex.unlock();
}
}
void join()
{
m_Thread.join();
}
};
int Soldier::count, Soldier::moneySpent;
boost::mutex Soldier::soldierMutex;
int main()
{
Soldier s1,s2,s3;
s1.start(20);
s2.start(30);
s3.start(40);
s1.join();
s2.join();
s3.join();
for (int i = 0; i < 100; ++i)
{
Soldier s;
s.start(30);
}
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
}
It looks like you're not waiting for the threads started in the loop to finish. Change the loop to:
for (int i = 0; i < 100; ++i)
{
Soldier s;
s.start(30);
s.join();
}
edit to explain further
The problem you saw was that the values printed out were wrong, so you assumed there was a race condition in the threads. The race in fact was when you printed the values - they were printed while not all the threads had a chance to execute
Based on this and your previous post (were it does not seem you have read all the answers yet). What you are looking for is some form of synchronization point to prevent the main() thread from exiting the application (because when the main thread exits the application all the children thread die).
This is why you call join() all the time to prevent the main() thread from exiting until the thread has exited. As a result of your usage though your loop of threads is not parallel and each thread is run in sequence to completion (so no real point in using the thread).
Note: join() like in Java waits for the thread to complete. It does not start the thread.
A quick look at the boost documentation suggests what you are looking for is a thread group which will allow you to wait for all threads in the group to complete before exiting.
//No compiler so this is untested.
// But it should look something like this.
// Note 2: I have not used boost::threads much.
int main()
{
boost::thread_group group;
boost::ptr_vector<boost::thread> threads;
for(int loop = 0; loop < 100; ++loop)
{
// Create an object.
// With the function to make it start. Store the thread in a vector
threads.push_back(new boost::thread(<Function To Call>));
// Add the thread to the group.
group.add(threads.back());
}
// Make sure main does not exit before all the threads have completed.
group.join_all();
}
If we go back to your example and retrofit your Soldier class:
int main()
{
boost::thread batallion;
// Make all the soldiers part of a group.
// When you start the thread make the thread join the group.
Soldier s1(batallion);
Soldier s2(batallion);
Soldier s3(batallion);
s1.start(20);
s2.start(30);
s3.start(40);
// Create 100 soldiers outside the loo
std::vector<Soldier> lotsOfSoldiers;
lotsOfSoldiers.reserve(100); // to prevent reallocation in the loop.
// Because you are using objects we need to
// prevent copying of them after the thread starts.
for (int i = 0; i < 100; ++i)
{
lotsOfSoldiers.push_back(Solder(batallion));
lotsOfSoldiers.back().start(30);
}
// Print out values while threads are still running
// Note you may get here before any thread.
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
batallion.join_all();
// Print out values when all threads are finished.
cout << "Total soldier: " << Soldier::count << '\n';
cout << "Money spent: " << Soldier::moneySpent << '\n';
}