显示从 std::condition_variable::wait 解锁

Showing the unlock from std::condition_variable::wait

提问人:davidj361 提问时间:10/8/2022 更新时间:10/9/2022 访问量:295

问:

我从 https://en.cppreference.com/w/cpp/thread/condition_variable/wait 读到“原子解锁锁”。我如何通过?我试图更好地理解条件变量的实际操作。我在下面写了一个尝试。wait()std::cout

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

using namespace std;

condition_variable cv;
mutex m;
bool stopped = false;

void f1() {
    unique_lock<mutex> ul{m};
    cout << "f1: " << ul.owns_lock() << endl;
    cv.wait(ul, [&]{
        cout << "f1: " << ul.owns_lock() << endl;
        return stopped;
    });
    cout << "f1 RUNNING\n";
    cout << "f1: " << ul.owns_lock() << endl;
}


void f2() {
    lock_guard<mutex> lg{m};
    cout << "f2 RUNNING\n";
}

int main() {
    unique_lock<mutex> ul{m};
    thread t1(&f1);
    thread t2(&f2);

    cout << ul.owns_lock() << endl;
    this_thread::sleep_for(chrono::seconds(1));
    stopped = true;
    cv.notify_one();
    cout << ul.owns_lock() << endl;
    ul.unlock();
    cout << ul.owns_lock() << endl;
    this_thread::sleep_for(chrono::seconds(1));

    t1.join();
    t2.join();
    return 0;
}
C++ C++11 标准 条件变量

评论

1赞 Sven Nilsson 10/8/2022
您永远不会看到 owns_lock() 返回 false,因为在 wait() 解锁互斥锁后,线程会立即进入睡眠状态。您可以通知线程(),然后它将执行谓词函数以确定是否继续等待,但在此检查期间将需要互斥锁,并且 owns_lock() 将返回 true。
0赞 OznOg 10/8/2022
这回答了你的问题吗?conditional_wait() 是如何在内核和硬件/汇编级别实现的?

答:

3赞 Remy Lebeau 10/8/2022 #1

std::unique_lock并使用满足 BasicLockable 要求的任何类类型。因此,只需编写自己的类来包装 ,然后就可以添加所需的任何日志记录。std::lock_guardstd::mutex

更新:但是,仅适用于,因此如果您编写自己的互斥包装器类,则必须改用。std:condition_variablestd::mutexstd::condition_variable_any

例如:

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

using namespace std;

struct LoggingMutex
{
    mutex m;

    void lock() {
        cout << "Locking" << endl;
        m.lock();
        cout << "Locked" << endl;
    }

    bool try_lock() {
        cout << "Attempting to lock" << endl;
        bool result = m.try_lock();
        cout << (result ? "Locked" : "Not locked") << endl;
        return result;
    }

    void unlock() {
        cout << "Unlocking" << endl;
        m.unlock()
        cout << "Unlocked" << endl;
    }
};

condition_variable_any cv;
LoggingMutex lm;
bool stopped = false;

void f1() {
    unique_lock<LoggingMutex> ul{lm};
    cout << "f1: " << ul.owns_lock() << endl;
    cv.wait(ul, [&]{
        cout << "f1: " << ul.owns_lock() << endl;
        return stopped;
    });
    cout << "f1 RUNNING\n";
    cout << "f1: " << ul.owns_lock() << endl;
}


void f2() {
    lock_guard<LoggingMutex> lg{lm};
    cout << "f2 RUNNING\n";
}

int main() {
    unique_lock<LoggingMutex> ul{lm};
    thread t1(&f1);
    thread t2(&f2);

    cout << ul.owns_lock() << endl;
    this_thread::sleep_for(chrono::seconds(1));
    stopped = true;
    cv.notify_one();
    cout << ul.owns_lock() << endl;
    ul.unlock();
    cout << ul.owns_lock() << endl;
    this_thread::sleep_for(chrono::seconds(1));

    t1.join();
    t2.join();
    return 0;
}

评论

1赞 Igor Tandetnik 10/9/2022
std::condition_variable具体采取;它不适用于 .您的示例实际上无法编译。您可能打算使用std::unique_lock<std::mutex>unique_lock<LoggingMutex>std::condition_variable_any