I was trying to understand the condition_variable available in C++ standard. So in the below test code I have written, I expect the func1 to be woken up after printing 50 numbers in main thread but here it prints all numbers only from main thread?
Could you please help me here to understand condition_variable better to indicate a certain thread to wake up
I have tried to understand condition variable using below code:
#include <stdio.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex mu;
std::condition_variable multiple;
bool isLoaded = false;
void func1()
{
std::unique_lock<std::mutex> unLock(mu);
multiple.wait(unLock, []() {return isLoaded; });
for (int i = 0; i < 100; i++)
{
cout << "This is from thread; " << i << endl;
}
}
int main()
{
std::thread t1(func1);
std::lock_guard<std::mutex> gaurd(mu);
cout << std::thread::hardware_concurrency()<< endl;
for (int i = 0; i < 100; i++)
{
if (i == 50)
{
isLoaded = true;
multiple.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(4));
}
cout << "This is from main; " << i << endl;
}
t1.join();
getchar();
return 0;
}
You never release mu in main thread. Try something like this:
int main()
{
std::thread t1(func1);
cout << std::thread::hardware_concurrency()<< endl;
for (int i = 0; i < 100; i++)
{
if (i == 50)
{
{
std::lock_guard<std::mutex> gaurd(mu);
isLoaded = true;
}
multiple.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(4));
}
cout << "This is from main; " << i << endl;
}
t1.join();
getchar();
return 0;
}
In general you need to keep your locks for absolute minimum of time you can.
You are taking mutex mu at start of your program and never let it go, so any other code under this mutex will never be executed.
Instead you should only hold it when you changing shared variables, something like:
{
std::lock_guard<std::mutex> gaurd(mu);
isLoaded = true;
multiple.notify_one();
}
Related
I am new to threading, and i am trying to write a function that keep outputing an variable while i should be able to change that variable at runtime, and the output should change to my input once I input a new value in. By the following program is not running as i expected, whats wrong here? is there anything i can reference to so i can build this funciton out?
int a;
void* ptr;
void* Input(void* arg){
while(true){
std::cin >> a;
std::cout << std::endl;
}
return ptr;
}
void* Output(void *arg){
while(true){
std::cout << a << std::endl;
}
return ptr;
}
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
}
Your main thread is not waiting for your child thread and exited when main() returned. To make your main thread to wait for children finish their jobs, you should call pthread_join() for them.
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
pthread_join(GetInput, NULL);
pthread_join(GetOutput, NULL);
return 0;
}
Here's another alternative using std::async() for your code.
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
int a;
std::mutex mtx_;
void Input(void* arg) {
while (true) {
int tmp_a;
std::cin >> tmp_a;
{
std::lock_guard<std::mutex> lock(mtx_);
a = tmp_a;
}
std::cout << std::endl;
}
}
void Output(void* arg) {
while (true) {
{
std::lock_guard<std::mutex> lock(mtx_);
std::cout << a << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
auto ft_in = std::async(std::launch::async, Input, &a);
auto ft_out = std::async(std::launch::async, Output, &a);
ft_in.wait();
ft_out.wait();
return 0;
}
Well,I don't know how to use pthread.
And it seems Mr.john-park or Ms.john-park already gave a answer.
But I think use thread is a better choice.
To use it,we should:
#include<thread>
After that,if u want to start a new thread,and "connect" it with a function(In fact,we usually do)
There is a class named thread.
First,we should
thread *thread name*(*function name*);
WARNING:function nameshould be without "(" and ")"
May because here should be a pointer.
Then,to the question.
Suppose we wrote:
thread GetInput(Input);
thread GetOutput(Output);
When u want to stop GetOutput some time and run GetInput,
just
GetInput.join()
Here's a not so good example:
#include <iostream>
#include <thread>
using namespace std;
void f1()
{
while (true)
{
cout << "THREAD 1!" << endl;
}
}
void f2()
{
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
thread t1(f1);
t1.join();
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
}
int main()
{
thread t2(f2);
return 0;
}
First,we started t2.
Then t2 started t1.
Now we can know why we use join().
If we don't join(),
It'll be hard for us to read the output because it'll close the cmd window quickly.
But we can know,
after t2 end,
return 0;
ran.
But if we used join()
Here's the output:
THREAD 2!
THREAD 2!
THREAD 2!
...(THREAD 2!*10)
THREAD 1!
THREAD 1!
...(Always THREAD 1!)
Thanks in advance for any help.
Trying to make a program that would create 6 threads, then each 2 seconds randomly choose one and make it print its number. I am obviously doing something wrong, because it just keeps printing 0-1-2-3-4-5 endlessly. The code is below.
Main question is, what should i do to make random threads unlock?
#include <thread>
#include <memory>
#include <chrono>
#include <condition_variable>
std::condition_variable* cv = new std::condition_variable();
std::mutex cv_m;
void threadFunc(std::shared_ptr<bool> flag2, int id)
{
while (true)
{
std::unique_lock<std::mutex> lock(cv_m);
cv->wait(lock);
if (true)
if (*flag2) std::cout << "Thread" << " " << id << std::endl;
}
}
int main() {
std::shared_ptr<bool> f2 = std::make_shared<bool>(false);
std::thread threads[6];
for (int i = 0; i < 6; i++)
threads[i] = std::thread(threadFunc, f2, i);
*f2 = true;
while (true)
{
cv->notify_one();
std::this_thread::sleep_for(std::chrono::seconds(2));
}
return 0;
}
You can use a condition variable for each thread, it should be false for each thread at the beginning, then change a random condition variable to true and notify all, this will make a random thread to wake up (the thread that owns that condition variable)
here is the full solution
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <unistd.h>
#include "UserInterruptHandler.h"
using namespace std;
UserInterruptHandler h;
condition_variable conditionalVariable;
mutex mtx;
bool flag = true;
void myMethod(int id, bool *canWork) {
unique_lock<mutex> ul(mtx);
while (flag) {
conditionalVariable.wait(ul,[=]{return *canWork;});
if(!flag)
break;
cout << "thread " << id << endl;
}
cout << "thread " << id << " exits.." << endl;
}
int main() {
cout << "input thread count" << endl;
int n;
cin >> n;
thread myThreads[n];
bool *canWork = new bool[n];
for (int i = 0; i < n; i++) {
canWork[i] = false;
myThreads[i] = thread(myMethod, i + 1, &canWork[i]);
}
while (!h.checkInterruption()) {
int i = rand() % n;
canWork[i] = true;
conditionalVariable.notify_all();
canWork[i] = false;
usleep(1000);
}
flag = false;
int i = 0;
for (thread &th:myThreads) {
canWork[i++] = true;
conditionalVariable.notify_all();
if (th.joinable())
th.join();
}
}
notice that here I am using header UserInterruptHandler.h to handle CTR+C event to end all threads gracefully
I want to send a broadcast signal from the main thread to all the other threads waiting for a condition. It seems to me that the broadcast signal comes to early to the threads.
#include <iostream>
#include <pthread.h>
#define NUM 4
#define SIZE 256
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_barrier_t barrier;
class cache{
int lv1;
public:
int write(int i){
lv1=i;
pthread_cond_broadcast(&cond);
}
};
cache c[NUM];
void *thread(void *arg){
int i = (int)arg;
for(;;){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
cout << "Thread: "<< i << endl;
//do some work
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid[NUM];
pthread_barrier_init(&barrier,NULL,NUM+1);
for(int i=0;i<NUM;i++){
pthread_create(&tid[i],NULL,thread,(void*)i);
}
//Sleep(2);
c[0].write(55); //broadcast signal
//Sleep(2);
c[1].write(44); //broadcast signal
for(int i=0;i<NUM;i++){
pthread_join(tid[i],NULL);
}
cout << "Hello world!" << endl;
return 0;
}
If I insert Sleep(2) in the main function, it works, but I do not want to wait a time but a synchronisation before calling pthread_broadcast.
I thought of a barrier, but pthread_cond_wait is blocking, right?
You need to read up on how condition variables are used. You also handled the integer arguments to your threads erroneously. Here is a fixed version, hopefully similar to what you wanted:
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#define NUM 4
#define SIZE 256
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_barrier_t barrier;
class cache{
int lv1;
public:
int write(int i) { lv1=i; }
const int val() { return lv1; }
};
cache c[NUM];
void *thread(void *arg)
{
int i = *(int*)arg;
for(;;) {
pthread_mutex_lock(&mutex);
// Check predicate, do not go to sleep if predicate is fulfilled
if (c[0].val() > 0 && c[1].val() > 0) {
cout << "Thread " << i << " leaving...\n";
pthread_mutex_unlock(&mutex);
return 0;
}
pthread_cond_wait(&cond, &mutex);
cout << "Thread wakeup: "<< i << endl;
// do some work
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid[NUM];
int arg[NUM];
for(int i=0; i<NUM; i++) {
arg[i] = i; // make a copy of i used by only one thread
pthread_create(&tid[i], NULL, thread,(void*)&arg[i]);
}
pthread_mutex_lock(&mutex);
c[0].write(55);
c[1].write(44);
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond); // Signal all threads that predicate is fulfilled
for(int i=0; i<NUM; i++) {
pthread_join(tid[i],NULL);
cout << "Joined " << i << '\n';
}
cout << "Hello world!" << endl;
return 0;
}
Sequence how I think it is
This is how it is right now I think, I still need a way to synchronise, before I send the broadcast signal.
In that picture, the first pthread_broadcast comes too early.
I'm trying to learn the condition variables, and I'm stuck at the following example. I thought that notify_one on consumers should unlock only one waiting consumer. But after starting it repeatedly it seems to me that this isn't the case. I've changed notify_one into notify_all and haven't noticed a change in behavior. After the producer calls notify_one on consumers I can see Get… being written on screen by more then one consumer.
Why is this happening?
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <chrono>
std::mutex mtx;
std::condition_variable produce,consume;
int cargo = 0; // shared value by producers and consumers
void consumer () {
std::unique_lock<std::mutex> lck(mtx);
while (cargo==0) consume.wait(lck);
std::cout << "Get" << cargo << " "<< std::this_thread::get_id() << '\n';
cargo--;
produce.notify_one();
}
void producer (int id) {
std::unique_lock<std::mutex> lck(mtx);
while (cargo!=0) produce.wait(lck);
std::cout << "Push" << id << " "<< std::this_thread::get_id() << '\n';
cargo += id;
consume.notify_one();
}
void c () {
while(1) {
consumer();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
void p(int n) {
while(1) {
producer(n);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main ()
{
std::thread consumers[5],producers[5];
for (int i=0; i<5; ++i) {
consumers[i] = std::thread(c);
producers[i] = std::thread(p,i+1);
}
for (int i=0; i<5; ++i) {
producers[i].join();
consumers[i].join();
}
return 0;
}
I was trying to write code for Producer-Consumer problem. Below code works fine most of the time but stuck sometimes because of "Lost Wake-up" (i guess). I tried thread sleep() but it didn't work. What modification is needed to handle this case in my code? Is semaphore can be helpful here ? If yes, how will i implement them here ?
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
using namespace std;
int product = 0;
boost::mutex mutex;
boost::condition_variable cv;
boost::condition_variable pv;
bool done = false;
void consumer(){
while(done==false){
//cout << "start c" << endl
boost::mutex::scoped_lock lock(mutex);
cv.wait(lock);
//cout << "wakeup c" << endl;
if (done==false)
{
cout << product << endl;
//cout << "notify c" << endl;
pv.notify_one();
}
//cout << "end c" << endl;
}
}
void producer(){
for(int i=0;i<10;i++){
//cout << "start p" << endl;
boost::mutex::scoped_lock lock(mutex);
boost::this_thread::sleep(boost::posix_time::microseconds(50000));
++product;
//cout << "notify p" << endl;
cv.notify_one();
pv.wait(lock);
//cout << "wakeup p" << endl;
}
//cout << "end p" << endl;
cv.notify_one();
done = true;
}
int main()
{
int t = 1000;
while(t--){
/*
This is not perfect, and is prone to a subtle issue called the lost wakeup (for example, producer calls notify()
on the condition, but client hasn't really called wait() yet, then both will wait() indefinitely.)
*/
boost::thread consumerThread(&consumer);
boost::thread producerThread(&producer);
producerThread.join();
consumerThread.join();
done =false;
//cout << "process end" << endl;
}
cout << "done" << endl;
getchar();
return 0;
}
Yes, you want a way to know (in the consumer) that you "missed" a signal. A semaphore can help. There's more than one way to skin a cat, so here's my simple take on it (using just c++11 standard library features):
class semaphore
{
private:
std::mutex mtx;
std::condition_variable cv;
int count;
public:
semaphore(int count_ = 0) : count(count_) { }
void notify()
{
std::unique_lock<std::mutex> lck(mtx);
++count;
cv.notify_one();
}
void wait() { return wait([]{}); } // no-op action
template <typename F>
auto wait(F&& func = []{}) -> decltype(std::declval<F>()())
{
std::unique_lock<std::mutex> lck(mtx);
while(count == 0){
cv.wait(lck);
}
count--;
return func();
}
};
For convenience, I added a convenience wait() overload that takes a function to be executed under the lock. This makes it possible for the consumer to operate the 'semaphore' without ever manually operating the lock (and still get the value of product without data-races):
semaphore sem;
void consumer() {
do {
bool stop = false;
int received_product = sem.wait([&stop] { stop = done; return product; });
if (stop)
break;
std::cout << received_product << std::endl;
std::unique_lock<std::mutex> lock(processed_mutex);
processed_signal.notify_one();
} while(true);
}
A fully working demo: Live on Coliru:
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <cassert>
class semaphore
{
private:
std::mutex mtx;
std::condition_variable cv;
int count;
public:
semaphore(int count_ = 0) : count(count_) { }
void notify()
{
std::unique_lock<std::mutex> lck(mtx);
++count;
cv.notify_one();
}
void wait() { return wait([]{}); } // no-op action
template <typename F>
auto wait(F&& func = []{}) -> decltype(std::declval<F>()())
{
std::unique_lock<std::mutex> lck(mtx);
while(count == 0){
cv.wait(lck);
}
count--;
return func();
}
};
semaphore sem;
int product = 0;
std::mutex processed_mutex;
std::condition_variable processed_signal;
bool done = false;
void consumer(int check) {
do {
bool stop = false;
int received_product = sem.wait([&stop] { stop = done; return product; });
if (stop)
break;
std::cout << received_product << std::endl;
assert(++check == received_product);
std::unique_lock<std::mutex> lock(processed_mutex);
processed_signal.notify_one();
} while(true);
}
void producer() {
std::unique_lock<std::mutex> lock(processed_mutex);
for(int i = 0; i < 10; ++i) {
++product;
sem.notify();
processed_signal.wait(lock);
}
done = true;
sem.notify();
}
int main() {
int t = 1000;
while(t--) {
std::thread consumerThread(&consumer, product);
std::thread producerThread(&producer);
producerThread.join();
consumerThread.join();
done = false;
std::cout << "process end" << std::endl;
}
std::cout << "done" << std::endl;
}
You seems to ignore that the variable done is also a shared state, to the same extend as product. Which can lead to several races conditions. In your case, I see at least one scenario where consumerThread make no progress:
The loop execute has intended
consumer executes, and is waiting at cv.wait(lock);
producer has finished the for loop, and notify consumer and is preempted
consumer wakes up, read "done==false", output product, read done == false again, wait on the condition
producer set done to true and exit
consumer is stuck forever
To avoid these kind of issues you should be holding a lock when reading or writing done. Btw your implementation is quite sequential, ie the producer and the consumer can only process a single piece of data at the time...