std :: condition_variable线程争用

时间:2014-06-24 22:43:57

标签: c++ multithreading c++11 condition-variable

我有一个问题,我的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;
}

1 个答案:

答案 0 :(得分:0)

由于您在错误的时间通知,因此条件变量不会相互通知。例如,如果onecv_one.notify()调用two之前调用cv_one.wait(lock) ,则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;
}