gpt4 book ai didi

c++ - 为什么 std::condition_variable 不等待并立即再次获得锁?

转载 作者:搜寻专家 更新时间:2023-10-31 02:02:15 24 4
gpt4 key购买 nike

我想学习一点线程,这是我的代码。

Foo.hpp

#include <Windows.h>
#include <mutex>
#include <thread>
#include <iostream>


class Foo {
public:
Foo(int i);

int my_number = 0;

static std::mutex mutex_open_table;

std::condition_variable close_table_condition_variable; //Non Static on purpose
bool notified_close_table = false;

void OpenTable();
void CloseTable();
};

Foo.Cpp

std::mutex Foo::mutex_open_table;


Foo::Foo(int i)
{
my_number = i;
}


void Foo::OpenTable()
{
while (true)
{

std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(mutex_open_table);

std::cout << "Open Table: " << my_number << std::endl;

Sleep(1000);

while (!notified_close_table) { // loop to avoid spurious wakeups

close_table_condition_variable.wait(lock);
}
std::cout << "Notified Table: " << my_number << std::endl;

Sleep(1000);

notified_close_table = false;
}
}

void Foo::CloseTable()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock{ mutex_open_table };
std::cout << "Close Table: " << my_number << std::endl;

Sleep(1000);

notified_close_table = true;
close_table_condition_variable.notify_one();

}
}

主.Cpp

int main()
{

Foo foo(1);
Foo foo2(2);

std::thread test2 = std::thread(&Foo::CloseTable, &foo);
std::thread test3 = std::thread(&Foo::OpenTable, &foo);


std::thread test4 = std::thread(&Foo::CloseTable, &foo2);
std::thread test5 = std::thread(&Foo::OpenTable, &foo2);

test2.join();
}

根据我的理解/我的大脑想法

带有 OpenTable 的线程只能打印:

std::cout << "Open Table: " << my_number << std::endl;

在此消息之后,必须执行 CloseTable,以便 OpenTable 可以继续。

std::cout << "Close Table: " << my_number << std::endl;

在此 OpenTables 之后,std::condition_variable 再次尝试锁定互斥锁,并且必须打印此消息。

std::cout << "Notified Table: " << my_number << std::endl;

带CloseTable函数的线程可以任意执行多次。

在启动程序时,有时会在“打开表”之后出现“通知表”

是不是我的想法有问题。或者我的代码有什么问题吗?

TL:DR 的思考过程是,对于每个“OpenTable”,之后都需要一个“Close Table”,然后是一个“Notified Table”。

备注:同时CloseTable可以随时多次执行并打印“CloseTable”。

最佳答案

考虑程序启动后的以下事件链:

  1. notified_close_table 初始化为 false
  2. CloseTable() 被执行。这没有前提。最后,notified_close_table 被设置为 true(此时 condition_variable::notify_one() 没有意义)。
  3. OpenTable() 被执行。
    1. 首先,打印“Open Table”。
    2. 然后 while (!notified_close_table) 中的检查立即失败(因为notified_close_table 已经设置为 trueCloseTable() 之前的方法)。
    3. 打印“通知表”。
    4. notified_close_table 设置为 false

所以这将打印“Close Table”=>“Open Table”=>“Notified Table”。

如果你想在每个打开/通知之间打印一个“关闭表”,你必须将 notified_close_table = false;OpenTable() 中向上移动,在while 循环:

    std::cout << "Open Table: " << my_number << std::endl;
Sleep(1000);
notified_close_table = false;
while (!notified_close_table) { // loop to avoid spurious wakeups
close_table_condition_variable.wait(lock);
}
std::cout << "Notified Table: " << my_number << std::endl;

其他改进:

  • 修复后,您可以将 while 循环更改为 do { ... } while 循环以省略第一个不必要的检查
  • 为了避免不必要的线程唤醒,condition_variable::notify_one() 应该在互斥体解锁后调用:

    void Foo::CloseTable()
    {
    while (true)
    {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
    std::unique_lock<std::mutex> lock{ mutex_open_table };
    std::cout << "Close Table: " << my_number << std::endl;
    Sleep(1000);
    notified_close_table = true;
    }
    close_table_condition_variable.notify_one();
    }
    }

关于c++ - 为什么 std::condition_variable 不等待并立即再次获得锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57639999/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com