Std::condition_variable线程争用

std::condition_variable thread contention

本文关键字:线程 争用 variable condition Std      更新时间:2023-10-16

我有一个问题,我的condition_variables似乎没有相互通知。从我所读到的看来,condition_variable不能正常工作的主要原因是锁只在"等待"线程中使用。也就是说,我下面的代码在wait和notify线程中都使用了互斥锁,但仍然不能正常运行。

我错过了什么吗?

谢谢。

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::condition_variable cv_one;
std::condition_variable cv_two;
std::mutex m_one;
std::mutex m_two;
void one(  )
{
  std::unique_lock< std::mutex > lock { m_one };
  cv_one.notify_one( );
  std::cout << "one" << std::endl;
}
void two(  )
{
  {
    std::unique_lock< std::mutex > lock { m_one };
    cv_one.wait( lock );
    std::cout << "two" << std::endl;
  }
  {
    std::unique_lock< std::mutex > lock { m_two };
    cv_two.notify_one(  );
  }
}
void three( )
{
  std::unique_lock< std::mutex > lock { m_two };
  cv_two.wait( lock );
  std::cout << "three" << std::endl;
}
int main( int argc, char **argv )
{
  std::thread thread_one( one );
  std::thread thread_two( two );
  std::thread thread_three( three );
  std::cin.get(  );
  cv_one.notify_all( );
  thread_three.join( );
  thread_two.join( );
  thread_one.join( );
  return 0;
}

条件变量没有相互通知,因为您在错误的时间进行了通知。例如,如果onetwo调用cv_one.wait(lock)之前调用cv_one.notify() ,那么two将永远阻塞。就two所见,在等待时,没有线程通知它。这是@v。Oddou的意思是,通知标志没有被存储。

std::cin行作为延迟,这就是为什么输出是正确的。在按下按钮所需的延迟时间内,所有线程都到达了它们等待条件变量的位置。

您可以在这个代码示例中看到发生的问题,它显示了线程在被唤醒时开始等待的时间。我切换到单个字符,这样输出就不会乱成一团。

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::condition_variable cv_one;
std::condition_variable cv_two;
std::mutex m_one;
std::mutex m_two;
void one()
{
    std::unique_lock< std::mutex > lock { m_one };
    std::cout << "x" << std::endl;
    cv_one.notify_one();
    std::cout << "a" << std::endl;
}
void two()
{
    {
        std::unique_lock< std::mutex > lock { m_one };
        std::cout << "y" << std::endl;
        cv_one.wait( lock );
        std::cout << "b" << std::endl;
    }
    {
        std::unique_lock< std::mutex > lock { m_two };
        cv_two.notify_one();
    }
}
void three()
{
    std::unique_lock< std::mutex > lock { m_two };
    std::cout << "z" << std::endl;
    cv_two.wait( lock );
    std::cout << "c" << std::endl;
}
int main( int argc, char **argv )
{
    std::thread thread_one(one);
    std::thread thread_two(two);
    std::thread thread_three(three);
    std::cout << "d" << std::endl;
    cv_one.notify_all();
    thread_three.join();
    thread_two.join();
    thread_one.join();
    return 0;
}