Reputation: 10527
I did a simple experiment to test that:
Code:
#include <pthread.h>
#include <unistd.h>
#include <cassert>
#include <iostream>
using namespace std;
pthread_mutex_t mt;
pthread_cond_t cond;
pthread_t tid;
void* tf(void*arg){
pthread_mutex_lock(&mt);
pthread_cond_wait(&cond, &mt);
cout<<"After main thread sleeps 3 seconds\n";
return NULL;
}
int main(){
assert(0==pthread_mutex_init(&mt,NULL));
pthread_create(&tid,NULL,tf,NULL);
sleep(3);
pthread_cond_signal(&cond);
pthread_join(tid,NULL);//Is 2nd parameter useful?
pthread_cond_destroy(&cond);
return 0;
}
But in fact, the sub thread will print "After main thread sleeps 3 seconds" at once. Where did I get wrong?
Thanks.
Upvotes: 1
Views: 1134
Reputation: 21560
Most importantly, since you attached the C++ tag to this question, use the C++ threading features, not the pthread library. You are not guaranteed to always have access to that (for example on windows), whereas std::thread
is designed to be cross platform and free from some of the annoyances that come with using the pthread()
library's C interface
Second, initialize your variables, C and C APIs are annoying like that. Third, you need to account for spurious wakeups, put a while loop around the condition variable wait, and attach an actual condition to it, for example
while (not_signalled) {
pthread_cond_wait(&cond, &mt);
}
What might be happening is that your thread gets woken up spuriously and then finishes since you don't have a while loop protecting against spurious wakeups
Working C++ code
#include <thread>
#include <iostream>
#include <chrono>
using std::cout;
using std::endl;
std::mutex mtx;
std::condition_variable cv;
bool has_signalled{false};
void th_function() {
// acquire the lock
auto lck = std::unique_lock<std::mutex>{mtx};
// loop to protect against spurious wakeups
while (!has_signalled) {
// sleep
cv.wait(lck);
}
cout << "Thread has been signalled" << endl;
}
int main() {
auto th = std::thread{th_function};
// sleep for 2 seconds
std::this_thread::sleep_for(std::chrono::seconds(2));
// signal and change the variable
{
std::lock_guard<std::mutex> lck{mtx};
has_signalled = true;
}
// signal
cv.notify_one();
th.join();
}
Upvotes: 4
Reputation: 18521
I'm not aware about the Linux threading functions but in Windows you would have to initialize the variable that corresponds to pthread_cond_t cond
in Linux.
There is a manpage for a function named pthread_cond_init
which seems to do exactly that.
Upvotes: 1