c++ 一个线程通知另一个线程需要多长时间?

hjzp0vay  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(71)

我想测量一个条件变量通知另一个等待的线程需要多长时间。我写了这个例子来尝试捕捉时间差:

bool ready{false};
mutex m;
condition_variable cv;
decltype(chrono::steady_clock::now()) t1;
decltype(chrono::steady_clock::now()) t2;

void notifying_thread() {
    {
        lock_guard<mutex> lg{m};
        ready = true;
    }
    t1 = chrono::steady_clock::now();
    cv.notify_one();
}

void waiting_thread() {
    unique_lock<mutex> ul{m};
    cv.wait(ul, [] { return ready; });
    t2 = chrono::steady_clock::now();
}

int main() {
    auto f1{async(notifying_thread)};
    auto f2{async(waiting_thread)};
    f1.get();
    f2.get();
    cout << chrono::duration_cast<chrono::microseconds>(t2 - t1).count() << " µs\n";
    return 0;
}

字符串
我做得对吗?我的chrono::steady_clock::now() s是否在正确的位置?平均时间约为25 µs,但有时甚至是负数。它怎么可能是负数?t1不应该总是在t2之前启动吗?async的启动策略是否相关?

zrfyljdw

zrfyljdw1#

你的推理中缺少了虚假的唤醒。

while (!stop_waiting())
{
    wait(lock);
}

字符串
wait(lock)可以返回,即使条件变量没有被通知。这就是 predicate 的作用。当有伪唤醒时,你会一直循环,直到条件被满足。
由于虚假唤醒,wait(lock)可能会在另一个线程notify_one之前解除阻塞,但在它设置ready = true之后。在这种情况下,t2可能比t1早。
此外,正如DanielLangr在评论中指出的那样,当条件在进入上述循环之前已经被填满时,wait(lock)永远不会被调用。同样在这种情况下,t2可以早于t1
此外,这两个线程并不是立即启动的,如果notifying_thread启动,而waiting_thread启动的时间要晚一些,那么你基本上是在测量这个时间,而不是通知条件变量所花费的时间。

相关问题