I'm trying to create a concurrent code where I execute a function per second, this function prints a character and waits a second on that thread. The behaviour I expect is to print each character after another but this doesn't happen, instead, it prints all of the characters of the inner loop execution. I'm not sure if this is somewhat related to an I/O operation or whatnot.
I've also tried to create an array of threads where each thread are created on the execution of the inner loop but the behaviour repeats, even if not calling join(). What might be wrong with the code?
The following code is what I've tried to do, and I used a clock to see if it was waiting the correct amount of time
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
void print_char();
int main() {
using Timer = std::chrono::high_resolution_clock;
using te = std::chrono::duration<double>;
using s = std::chrono::seconds;
te interval;
for (int i = 0; i < 100; i++) {
auto a = Timer::now();
for (int j = 0; j < i; j++) {
std::thread t(print_char);
t.join();
}
auto b = Timer::now();
interval = b-a;
std::cout << std::chrono::duration_cast<s>(interval).count();
std::cout << std::endl;
}
return 0;
}
void print_char() {
std::cout << "*";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
The behaviour I expect is to print each character after another but this doesn't happen, instead, it prints all of the characters of the inner loop execution.
You need to flush the output stream in order to see the text:
std::cout << "*" << std::flush;
std::endl contains call to std::flush in it and this is why you see whole lines to be displayed once the inner loop is complete. Your threads do add the '*' characters once per second, you just don't see them being added until the stream is flushed.
Consider the code
std::thread t(print_char);
t.join();
The first line creates and start a thread. The second line immediately wait for the thread to end. That makes your program serial and not parallel. In fact, it's no different than calling the function directly instead of creating the thread.
If you want to have the thread operate in parallel and independently from your main thread, you should have the loop in the thread function itself instead. Perhaps something like
std::atomic<bool> keep_running = true;
void print_char() {
while (keep_running) {
std::cout << "*";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
Then in the main function you just create the thread, and do something else until you want the thread to end.
std::thread t(print_char);
// Do something else...
keep_running = false;
t.join();
In regard to your current code, it's really no different than
for (int i = 0; i < 100; i++) {
auto a = Timer::now();
for (int j = 0; j < i; j++) {
print_char();
}
auto b = Timer::now();
interval = b-a;
std::cout << std::chrono::duration_cast<s>(interval).count();
std::cout << std::endl;
}
Related
I am looking at multithreading and written a basic producer/consumer. I have two issues with the producer/consumer written below. 1) Even by setting the consumer sleep time lower than the producer sleep time, the producer still seems to execute quicker. 2) In the consumer I have duplicated the code in the case where the producer finishes adding to the queue, but there is still elements in the queue. Any advise for a better way of structuring the code?
#include <iostream>
#include <queue>
#include <mutex>
class App {
private:
std::queue<int> m_data;
bool m_bFinished;
std::mutex m_Mutex;
int m_ConsumerSleep;
int m_ProducerSleep;
int m_QueueSize;
public:
App(int &MaxQueue) :m_bFinished(false), m_ConsumerSleep(1), m_ProducerSleep(5), m_QueueSize(MaxQueue){}
void Producer() {
for (int i = 0; i < m_QueueSize; ++i) {
std::lock_guard<std::mutex> guard(m_Mutex);
m_data.push(i);
std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(m_ProducerSleep));
}
m_bFinished = true;
}
void Consumer() {
while (!m_bFinished) {
if (m_data.size() > 0) {
std::lock_guard<std::mutex> guard(m_Mutex);
std::cout << "Consumer Thread, queue element: " << m_data.front() << " size: " << m_data.size() << std::endl;
m_data.pop();
}
else {
std::cout << "No elements, skipping" << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(m_ConsumerSleep));
}
while (m_data.size() > 0) {
std::lock_guard<std::mutex> guard(m_Mutex);
std::cout << "Emptying remaining elements " << m_data.front() << std::endl;
m_data.pop();
std::this_thread::sleep_for(std::chrono::seconds(m_ConsumerSleep));
}
}
};
int main()
{
int QueueElements = 10;
App app(QueueElements);
std::thread consumer_thread(&App::Consumer, &app);
std::thread producer_thread(&App::Producer, &app);
producer_thread.join();
consumer_thread.join();
std::cout << "loop exited" << std::endl;
return 0;
}
You should use condition_variable. Don't use sleep for threads.
Main scheme:
Producer pushes value under lock and signals condition_variable.
Consumer waits under lock on condition variable and checks predicate to prevent spurious wakeups.
My version:
#include <iostream>
#include <queue>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <atomic>
class App {
private:
std::queue<int> m_data;
std::atomic_bool m_bFinished;
std::mutex m_Mutex;
std::condition_variable m_cv;
int m_QueueSize;
public:
App(int MaxQueue)
: m_bFinished(false)
, m_QueueSize(MaxQueue)
{}
void Producer()
{
for (int i = 0; i < m_QueueSize; ++i)
{
{
std::unique_lock<std::mutex> lock(m_Mutex);
m_data.push(i);
}
m_cv.notify_one();
std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
}
m_bFinished = true;
}
void Consumer()
{
do
{
std::unique_lock<std::mutex> lock(m_Mutex);
while (m_data.empty())
{
m_cv.wait(lock, [&](){ return !m_data.empty(); }); // predicate an while loop - protection from spurious wakeups
}
while(!m_data.empty()) // consume all elements from queue
{
std::cout << "Consumer Thread, queue element: " << m_data.front() << " size: " << m_data.size() << std::endl;
m_data.pop();
}
} while(!m_bFinished);
}
};
int main()
{
int QueueElements = 10;
App app(QueueElements);
std::thread consumer_thread(&App::Consumer, &app);
std::thread producer_thread(&App::Producer, &app);
producer_thread.join();
consumer_thread.join();
std::cout << "loop exited" << std::endl;
return 0;
}
Also note, that it's better to use atomic for end flag, when you have deal with concurrent threads, because theoretically value of the m_bFinished will be stored in the cache-line and if there is no cache invalidation in the producer thread, the changed value can be unseen from the consumer thread. Atomics have memory fences, that guarantees, that value will be updated for other threads.
Also you can take a look on memory_order page.
First, you should use a condition variable instead of a delay on the consumer. This way, the consumer thread only wakes up when the queue is not empty and the producer notifies it.
That said, the reason why your producer calls are more frequent is the delay on the producer thread. It's executed while holding the mutex, so the consumer will never execute until the delay is over. You should release the mutex before calling sleep_for:
for (int i = 0; i < m_QueueSize; ++i) {
/* Introduce a scope to release the mutex before sleeping*/
{
std::lock_guard<std::mutex> guard(m_Mutex);
m_data.push(i);
std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
} // Mutex is released here
std::this_thread::sleep_for(std::chrono::seconds(m_ProducerSleep));
}
I was asked this question in an interview. I was pretty clueless.
So I decided to learn some multithreading and hopefully find an answer to this question.
I need to use 3 threads to print the output: 01020304050607.....
Thread1: prints 0
Thread2: prints odd numbers
Thread3: prints even numbers
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv1, cv2, cv3;
int count = 0;
void printzero(int end)
{
while (count <= end)
{
std::unique_lock<std::mutex> lock(m);
cv1.wait(lock);
std::cout << 0 << " ";
++count;
if (count % 2 == 1)
{
lock.unlock();
cv2.notify_one();
}
else
{
lock.unlock();
cv3.notify_one();
}
}
}
void printodd(int end)
{
while (count <= end)
{
std::unique_lock<std::mutex> lock(m);
cv2.wait(lock);
if (count % 2 == 1)
{
std::cout << count << " ";
++count;
lock.unlock();
cv1.notify_one();
}
}
}
void printeven(int end)
{
while (count <= end)
{
std::unique_lock<std::mutex> lock(m);
cv3.wait(lock);
if (count % 2 == 0)
{
std::cout << count << " ";
++count;
lock.unlock();
cv1.notify_one();
}
}
}
int main()
{
int end = 10;
std::thread t3(printzero, end);
std::thread t1(printodd, end);
std::thread t2(printeven, end);
cv1.notify_one();
t1.join();
t2.join();
t3.join();
return 0;
}
My solution seems to be in a deadlock situation. I'm not even sure if the logic is correct. Please help
There are several issues with your code. Here is what you need to do in order to make it work:
Revise your while (count <= end) check. Reading count without synchronization is undefined behavior (UB).
Use a proper predicate with std::condition_variable::wait. Problems of your code without predicate:
If notify_one is called before wait then the notification is lost. In the worst case, main's call to notify_one is executed before the threads start running. As a result, all threads may wait indefinitely.
Spurious wakeups may disrupt your program flow. See also cppreference.com on std::condition variable.
Use std::flush (just to be sure).
I played around with your code quite a lot. Below you find a version where I applied my suggested fixes. In addition, I also experimented with some other ideas that came to my mind.
#include <cassert>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
// see the `std::mutex` for an example how to avoid global variables
std::condition_variable cv_zero{};
std::condition_variable cv_nonzero{};
bool done = false;
int next_digit = 1;
bool need_zero = true;
void print_zero(std::mutex& mt) {
while(true) {// do not read shared state without holding a lock
std::unique_lock<std::mutex> lk(mt);
auto pred = [&] { return done || need_zero; };
cv_zero.wait(lk, pred);
if(done) break;
std::cout << 0 << "\t"
<< -1 << "\t"// prove that it works
<< std::this_thread::get_id() << "\n"// prove that it works
<< std::flush;
need_zero = false;
lk.unlock();
cv_nonzero.notify_all();// Let the other threads decide which one
// wants to proceed. This is probably less
// efficient, but preferred for
// simplicity.
}
}
void print_nonzero(std::mutex& mt, int end, int n, int N) {
// Example for `n` and `N`: Launch `N == 2` threads with this
// function. Then the thread with `n == 1` prints all odd numbers, and
// the one with `n == 0` prints all even numbers.
assert(N >= 1 && "number of 'nonzero' threads must be positive");
assert(n >= 0 && n < N && "rank of this nonzero thread must be valid");
while(true) {// do not read shared state without holding a lock
std::unique_lock<std::mutex> lk(mt);
auto pred = [&] { return done || (!need_zero && next_digit % N == n); };
cv_nonzero.wait(lk, pred);
if(done) break;
std::cout << next_digit << "\t"
<< n << "\t"// prove that it works
<< std::this_thread::get_id() << "\n"// prove that it works
<< std::flush;
// Consider the edge case of `end == INT_MAX && next_digit == INT_MAX`.
// -> You need to check *before* incrementing in order to avoid UB.
assert(next_digit <= end);
if(next_digit == end) {
done = true;
cv_zero.notify_all();
cv_nonzero.notify_all();
break;
}
++next_digit;
need_zero = true;
lk.unlock();
cv_zero.notify_one();
}
}
int main() {
int end = 10;
int N = 2;// number of threads for `print_nonzero`
std::mutex mt{};// example how to pass by reference (avoiding globals)
std::thread t_zero(print_zero, std::ref(mt));
// Create `N` `print_nonzero` threads with `n` in [0, `N`).
std::vector<std::thread> ts_nonzero{};
for(int n=0; n<N; ++n) {
// Note that it is important to pass `n` by value.
ts_nonzero.emplace_back(print_nonzero, std::ref(mt), end, n, N);
}
t_zero.join();
for(auto&& t : ts_nonzero) {
t.join();
}
}
I have some problem with st::async when is use this in other function other than Main function,
suppose, I have functions like flowing :
void printData()
{
for (size_t i = 0; i < 5; i++)
{
std::cout << "Test Function" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void runningAsync()
{
auto r = std::async(std::launch::async, test);
}
int main()
{
runningAsync();
std::cout << "Main Function" << std::endl;
}
the output of this code is :
Test Function
Test Function
Test Function
Test Function
Test Function
Main Function
that is not good, Main thread wait for other thread that be end.
I want runningAsync() function run in other thread and at the same time "Main Function" in main thread print on screan, this is possible with std::thread.
is that way for this running this functions an same time (concurrency)?
The reason is that std::async returns a std::future which you store in an auto variable. As soon as your future runs out of scope (at the end of runningAsync()!), its destructor blocks until the task is finished. If you do not want that, you could for example store the future in a global container.
This QUESTION answered in :
main thread waits for std::async to complete
Can I use std::async without waiting for the future limitation?
Whoever, If you store the std::future object, its lifetime will be extended to the end of main and you get the behavior you want.
void printData()
{
for (size_t i = 0; i < 5; i++)
{
std::cout << "Test Function" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
std::future<void> runningAsync()
{
return std::async(std::launch::async, test);
}
int main()
{
auto a = runningAsync();
std::cout << "Main Function" << std::endl;
}
That's a problem because std::future's destructor may block and wait for the thread to finish. see this link for more details
This is related to the second answer to this question.
My test code is below. I'm trying to launch a thread, and then to make it stop using the std::atomic_flag. Then the thread should output a number of loop executions and total duration, and stop.
std::atomic_flag keepRunning = ATOMIC_FLAG_INIT;
void F()
{
keepRunning.test_and_set();
long long unsigned count = 0;
const time_t start = time(nullptr);
while (keepRunning.test_and_set())
{
std::cout << '.';
++count;
}
const time_t duration = time(nullptr) - start;
std::cout << count << '\t' << duration << std::endl;
}
int main()
{
std::thread t(F);
keepRunning.clear();
t.join();
}
The problem is that the thread doesn't stop.
Why is that?
Compiler: g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
OS: guest OS Ubuntu 14.04 on the macOS Sierra Ver 10.12.2 host
Compilation flags - I tried -O0 and -O4, and it didn't make any difference.
It does not stop (most of the time) because the loop in F will probably never see a cleared flag.
Assuming that the creation of a thread will take some time, keepRunning.clear() in main is likely to run first.
When F finally gets to run, it immediately sets the value and enters a loop that will never see a cleared flag and therefore never quits.
Instead of initially setting the flag value in F, a solution is to initialize it to true. However, std::atomic_flag does not let you do that because of its limited interface (this design is on purpose,std::atomic_flag is supposed to be used as a low-level building block for other primitives).
You could use a std::atomic<bool>, initialize it to true and remove the initial store(true) in F. For demo purposes, I added a sleep_for statement before clearing the flag in main.
std::atomic<bool> keepRunning{true};
void F()
{
long long unsigned count = 0;
const time_t start = time(nullptr);
while (keepRunning)
{
std::cout << '.';
++count;
}
const time_t duration = time(nullptr) - start;
std::cout << count << '\t' << duration << std::endl;
}
int main()
{
std::thread t(F);
std::this_thread::sleep_for(1s); // optional
keepRunning = false;
t.join();
}
In your F() you ignore the output from the first keepRunning.test_and_set(). Your attempt to initialize the flag there causes a race with the keepRunning.clear() statement in main(). Depending on which of these statements runs first you either get the intended behavior or have ignored clear() call and a never ending thread.
By the time F() had a chance to run, the flag should be already initialized with the correct value. Moving that initial test_and_set() into main() prevents the race:
std::atomic_flag keepRunning = ATOMIC_FLAG_INIT;
void F()
{
long long unsigned count = 0;
const time_t start = time(nullptr);
while (keepRunning.test_and_set())
{
std::cout << '.';
++count;
}
const time_t duration = time(nullptr) - start;
std::cout << count << '\t' << duration << std::endl;
}
int main()
{
keepRunning.test_and_set();
std::thread t(F);
keepRunning.clear();
t.join();
}
Now the flag is effectively only changed in main() and only "read" in F().
As far as I know, such use of static storage within lambda is legal. Essentially it counts number of entries into the closure:
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
typedef std::pair<int,int> mypair;
std::ostream &operator<< (std::ostream &os, mypair const &data) {
return os << "(" << data.first << ": " << data.second << ") ";
}
int main()
{
int n;
std::vector<mypair> v;
std::cin >> n;
v.reserve(n);
std::for_each(std::begin(v), std::end(v), [](mypair& x) {
static int i = 0;
std::cin >> x.second;
x.first = i++;
});
std::for_each(std::begin(v), std::end(v), [](mypair& x) {
std::cout << x;
});
return 0;
}
Let assume I have a container 'workers' of threads.
std::vector<std::thread> workers;
for (int i = 0; i < 5; i++) {
workers.push_back(std::thread([]()
{
std::cout << "thread #" << "start\n";
doLengthyOperation();
std::cout << "thread #" << "finish\n";
}));
}
Code in doLengthyOperation() is contained and self-sufficient operation, akin a new process creation.
Provided I join them using for_each and the stored variable in question must count number of active tasks, not just number of entries, what possible implementations for such counter are there, if I want to avoid to rely onto global variables to avoid someone else messing up with it and allowing automatic support for separate "flavors" of threads.
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
Surrounding scope would die quickly after finishing thread starts, may repeat , adding new threads to the container is possible, and that must be global variable, which I want to avoid. More of, the whole operation is a template
The best way to handle this is to capture an instance of std::atomic<int> which provides a thread safe counter. Depending on the lifetime of lambdas and the surrounding scope, you may wish to capture by reference or shared pointer.
To take your example:
std::vector<std::thread> workers;
auto counter = std::make_shared<std::atomic<int>>(0);
for (int i = 0; i < 5; i++) {
workers.push_back(std::thread([counter]()
{
std::cout << "thread #" << "start\n";
(*counter)++;
doLengthyOperation();
(*counter)--;
std::cout << "thread #" << "finish\n";
}));
}