C++11 std::condition_variable - notify_one() 未按预期运行?
C++11 std::condition_variable - notify_one() not behaving as expected?
我看不出这个程序有任何实际用途,但在试验 c++ 11 并发性和 conditional_variables 时,我偶然发现了一些我不完全理解的东西。
起初我假设使用 notify_one()
将允许下面的程序运行。然而,实际上程序只是在打印完一个之后就卡住了。当我切换到使用 notify_all()
时,程序做了我想要它做的事情(按顺序打印所有自然数)。我相信已经以各种形式提出了这个问题。但我的具体问题是 doc 我在哪里读错了。
我认为 notify_one()
应该有效,因为以下陈述。
If any threads are waiting on *this, calling notify_one unblocks one of the waiting threads.
看下面只有一个线程会在给定时间被阻塞,对吗?
class natural_number_printer
{
public:
void run()
{
m_odd_thread = std::thread(
std::bind(&natural_number_printer::print_odd_natural_numbers, this));
m_even_thread = std::thread(
std::bind(&natural_number_printer::print_even_natural_numbers, this));
m_odd_thread.join();
m_even_thread.join();
}
private:
std::mutex m_mutex;
std::condition_variable m_condition;
std::thread m_even_thread;
std::thread m_odd_thread;
private:
void print_odd_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 1) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
void print_even_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 0) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
};
提供的代码 "works" 正确并被设计卡住。 documentation
中描述了原因
The effects of notify_one()/notify_all() and
wait()/wait_for()/wait_until() take place in a single total order, so
it's impossible for notify_one() to, for example, be delayed and
unblock a thread that started waiting just after the call to
notify_one() was made.
一步一步的逻辑是
print_odd_natural_numbers
线程已启动
print_even_natural_numbers
线程也已启动。
print_even_natural_numbers
的 m_condition.notify_all();
行在 print_odd_natural_numbers
线程到达 m_condition.wait(lock);
行之前执行。
- 执行了
print_odd_natural_numbers
的m_condition.wait(lock);
行,线程卡住了。
print_even_natural_numbers
的 m_condition.wait(lock);
行被执行,线程也被卡住了。
我看不出这个程序有任何实际用途,但在试验 c++ 11 并发性和 conditional_variables 时,我偶然发现了一些我不完全理解的东西。
起初我假设使用 notify_one()
将允许下面的程序运行。然而,实际上程序只是在打印完一个之后就卡住了。当我切换到使用 notify_all()
时,程序做了我想要它做的事情(按顺序打印所有自然数)。我相信已经以各种形式提出了这个问题。但我的具体问题是 doc 我在哪里读错了。
我认为 notify_one()
应该有效,因为以下陈述。
If any threads are waiting on *this, calling notify_one unblocks one of the waiting threads.
看下面只有一个线程会在给定时间被阻塞,对吗?
class natural_number_printer
{
public:
void run()
{
m_odd_thread = std::thread(
std::bind(&natural_number_printer::print_odd_natural_numbers, this));
m_even_thread = std::thread(
std::bind(&natural_number_printer::print_even_natural_numbers, this));
m_odd_thread.join();
m_even_thread.join();
}
private:
std::mutex m_mutex;
std::condition_variable m_condition;
std::thread m_even_thread;
std::thread m_odd_thread;
private:
void print_odd_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 1) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
void print_even_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 0) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
};
提供的代码 "works" 正确并被设计卡住。 documentation
中描述了原因The effects of notify_one()/notify_all() and wait()/wait_for()/wait_until() take place in a single total order, so it's impossible for notify_one() to, for example, be delayed and unblock a thread that started waiting just after the call to notify_one() was made.
一步一步的逻辑是
print_odd_natural_numbers
线程已启动print_even_natural_numbers
线程也已启动。print_even_natural_numbers
的m_condition.notify_all();
行在print_odd_natural_numbers
线程到达m_condition.wait(lock);
行之前执行。- 执行了
print_odd_natural_numbers
的m_condition.wait(lock);
行,线程卡住了。 print_even_natural_numbers
的m_condition.wait(lock);
行被执行,线程也被卡住了。