“pthread_cond_wait”没有等待主线程进入睡眠状态,为什么?

时间:2017-06-25 04:43:16

标签: c++ linux multithreading variables conditional

我做了一个简单的实验来测试:

  1. 主线程创建子线程。
  2. Subthread等待主线程发信号通知条件变量。
  3. 主线程休眠3秒并发出“cond”信号。然后我希望子线程将从“cond_wait”中唤醒并打印。
  4. 代码:

    #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;
    }
    

    但事实上,子线程将立即打印“主线程休眠3秒后”。我哪里弄错了?

    感谢。

2 个答案:

答案 0 :(得分:4)

最重要的是,由于您将C ++标记附加到此问题,因此请使用C ++线程功能,而不是pthread库。您不能保证始终可以访问它(例如在Windows上),而std::thread被设计为跨平台并且没有使用pthread()库的C接口带来的一些烦恼< / p>

其次,初始化你的变量,C和C API很烦人。第三,你需要考虑虚假的唤醒,在条件变量等待时放一个while循环,并附加一个实际条件,例如

while (not_signalled) {
    pthread_cond_wait(&cond, &mt);
}

可能发生的事情是你的线程被虚假唤醒然后结束,因为你没有一个while循环来防止虚假的唤醒

使用C ++代码

#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();
}

答案 1 :(得分:1)

我不了解Linux线程功能,但在Windows中,您必须初始化与Linux中pthread_cond_t cond对应的变量。

有一个名为pthread_cond_init的函数的联机帮助页似乎就是这样。