Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Conditional Variables and notify_all

27 views
Skip to first unread message

Doug Mika

unread,
Jul 24, 2015, 3:28:53 PM7/24/15
to
Hi, I am trying to use two threads to solve the Fibanacci numbers (for educational purposes only). But why when in main() does my cvOne.notify_all() not notify my thread t1 that it may proceed past its wait()? (ie. why does the following program not proceed?)

#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>

using namespace std;

void functionOne();
void functionTwo();

mutex mtx;
condition_variable cvOne, cvTwo;
long t1Value=1, t2Value=2;

int main()
{
cout<<"Solution: "<<endl;
thread t1(functionOne);
thread t2(functionTwo);
cvOne.notify_all();
t1.join();
t2.join();
cout<<" t1="<<t1Value<<endl;
cout<<" t2="<<t2Value<<endl;

return 0;
}

void functionOne(){
unique_lock<std::mutex> lck(mtx);
while(t1Value<4000000){
cout<<"t1: inside while\n";
cvOne.wait(lck);
cout<<"t1 is adding"<<endl;
t1Value+=t2Value;
cvTwo.notify_all();
}
}

void functionTwo(){
unique_lock<std::mutex> lck(mtx);
while(t2Value<4000000){
cout<<"t2: inside while\n";
cvTwo.wait(lck);
cout<<"t2 is adding"<<endl;
t2Value+=t1Value;
cvOne.notify_all();
}
}


Melzzzzz

unread,
Jul 24, 2015, 3:43:04 PM7/24/15
to
On Fri, 24 Jul 2015 12:28:36 -0700 (PDT)
Doug Mika <doug...@gmail.com> wrote:

> Hi, I am trying to use two threads to solve the Fibanacci numbers
> (for educational purposes only). But why when in main() does my
> cvOne.notify_all() not notify my thread t1 that it may proceed past
> its wait()? (ie. why does the following program not proceed?)

Because both threads are waiting on condition.


Doug Mika

unread,
Jul 24, 2015, 3:49:05 PM7/24/15
to
Yes, but thread 1 is waiting on condition variable cvOne (which I notify), and thread 2 is waiting on condition variable cvTwo (which thread 1 is to notify). Why doesn't thread 1 proceed if it's waiting on cvOne, and I notify cvOne in main?

Melzzzzz

unread,
Jul 24, 2015, 3:57:22 PM7/24/15
to
On Fri, 24 Jul 2015 12:48:55 -0700 (PDT)
Doug Mika <doug...@gmail.com> wrote:

> On Friday, July 24, 2015 at 2:43:04 PM UTC-5, Melzzzzz wrote:
> > On Fri, 24 Jul 2015 12:28:36 -0700 (PDT)
> > Doug Mika <doug...@gmail.com> wrote:
> >
> > > Hi, I am trying to use two threads to solve the Fibanacci numbers
> > > (for educational purposes only). But why when in main() does my
> > > cvOne.notify_all() not notify my thread t1 that it may proceed
> > > past its wait()? (ie. why does the following program not proceed?)
> >
> > Because both threads are waiting on condition.
>
> Yes, but thread 1 is waiting on condition variable cvOne (which I
> notify), and thread 2 is waiting on condition variable cvTwo (which
> thread 1 is to notify). Why doesn't thread 1 proceed if it's waiting
> on cvOne, and I notify cvOne in main?

Because there is no guarantee that you will be waiting on notify, that
is, notify can be missed.


Doug Mika

unread,
Jul 24, 2015, 4:00:57 PM7/24/15
to
I don't understand? I wait on a conditional variable which I then notify with another thread. Shouldn't that cause the waiting thread to proceed?

Melzzzzz

unread,
Jul 24, 2015, 4:03:51 PM7/24/15
to
On Fri, 24 Jul 2015 13:00:38 -0700 (PDT)
Your mistake is that you wait unconditionally. That does not works.


Doug Mika

unread,
Jul 24, 2015, 4:14:53 PM7/24/15
to
I hate to say it, but I still don't think I get it. What would I have to change in the above code to make the threads calculate the Fibanacci series?

Melzzzzz

unread,
Jul 24, 2015, 5:13:40 PM7/24/15
to
On Fri, 24 Jul 2015 13:14:44 -0700 (PDT)
#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>

using namespace std;

void functionOne();
void functionTwo();

mutex mtx;
condition_variable cv;
long t1Value=1, t2Value=2;

int main()
{
cout<<"Solution: "<<endl;
thread t1(functionOne);
thread t2(functionTwo);
// cvOne.notify_all();
t1.join();
t2.join();
cout<<" t1="<<t1Value<<endl;
cout<<" t2="<<t2Value<<endl;

return 0;
}

bool added=false;
void functionOne(){
unique_lock<std::mutex> lck(mtx);
while(t1Value<4000000){
cout<<"t1: inside while\n";
cout<<"t1 is adding"<<endl;
t1Value+=t2Value;
added = true;
cv.notify_one();
while(added)cv.wait(lck);
}
}

void functionTwo(){
unique_lock<std::mutex> lck(mtx);
while(t2Value<4000000){
cout<<"t2: inside while\n";
while(!added)cv.wait(lck);
cout<<"t2 is adding"<<endl;
t2Value+=t1Value;
added = false;
cv.notify_one();
}
}

Melzzzzz

unread,
Jul 24, 2015, 5:24:48 PM7/24/15
to
And if you want to harden it a bit:

#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>

using namespace std;

void functionOne();
void functionTwo();

mutex mtx;
condition_variable cv;
long t1Value=1, t2Value=2;

int main()
{
cout<<"Solution: "<<endl;
thread t1(functionOne);
thread t2(functionTwo);
// cvOne.notify_all();
t1.join();
t2.join();
cout<<" t1="<<t1Value<<endl;
cout<<" t2="<<t2Value<<endl;

return 0;
}

bool added=false,exited=false;
void functionOne(){
unique_lock<std::mutex> lck(mtx);
while(t1Value<4000000 && !exited){
cout<<"t1: inside while\n";
cout<<"t1 is adding"<<endl;
t1Value+=t2Value;
added = true;
cv.notify_one();
while(added && !exited)cv.wait(lck);
}
exited = true;
}

void functionTwo(){
unique_lock<std::mutex> lck(mtx);
while(t2Value<4000000 && !exited){
cout<<"t2: inside while\n";
while(!added && !exited)cv.wait(lck);
cout<<"t2 is adding"<<endl;
t2Value+=t1Value;
added = false;
cv.notify_one();
}
exited = true;
}

Marcel Mueller

unread,
Jul 24, 2015, 5:58:20 PM7/24/15
to
On 24.07.15 21.28, Doug Mika wrote:
> mutex mtx;
> condition_variable cvOne, cvTwo;
> long t1Value=1, t2Value=2;
>
> int main()
> {
> cout<<"Solution: "<<endl;
> thread t1(functionOne);
> thread t2(functionTwo);
> cvOne.notify_all();

Here is a race condition. It is not ensured that t1 is already waiting
for the condvar.

> void functionOne(){
> unique_lock<std::mutex> lck(mtx);
> while(t1Value<4000000){
> cout<<"t1: inside while\n";
> cvOne.wait(lck);
> cout<<"t1 is adding"<<endl;
> t1Value+=t2Value;
> cvTwo.notify_all();
> }
> }


Marcel

Doug Mika

unread,
Jul 24, 2015, 6:15:22 PM7/24/15
to
Well, I figured out what the problem was with my original program, and I thought I'd post the reason why it failed. The main thread executed cvOne.notify_all() BEFORE thread t1 reached the point where it waits on the condition variable, that is, the notify was executed before even a condition variable was told to wait.;-) Thought I'd post for those interested. Ah, the simple mistakes.

seeplus

unread,
Jul 24, 2015, 11:19:02 PM7/24/15
to
On Saturday, July 25, 2015 at 8:15:22 AM UTC+10, Doug Mika wrote:
>
> Well, I figured out what the problem was with my original program, and I >thought I'd post the reason why it failed. The main thread executed >cvOne.notify_all() BEFORE thread t1 reached the point where it waits on the >condition variable,

Thanks for posting the answer.
Simple and obvious when you see it like that, but easy to overlook
when you are concentrating on some other area.
0 new messages