【发布时间】:2020-04-07 18:14:57
【问题描述】:
又沉迷于学习并发,尝试解决this problem。
简而言之,我有一个类和 3 个函数。我需要同步他们的通话(需要打印FirstSecondThird)。
下面的代码会更清楚:
std::function<void()> printFirst = []() { std::cout << "First"; };
std::function<void()> printSecond = []() { std::cout << "Second"; };
std::function<void()> printThird = []() { std::cout << "Third"; };
class Foo {
std::condition_variable cv;
bool mfirst,msecond;
std::mutex mtx;
public:
Foo() {
mfirst = false;
msecond = false;
}
void first(std::function<void()> printFirst) {
std::unique_lock<std::mutex> l(mtx);
printFirst();
mfirst = true;
}
void second(std::function<void()> printSecond) {
std::unique_lock<std::mutex> l(mtx);
cv.wait(l, [this]{return mfirst == true; });
printSecond();
msecond = true;
}
void third(std::function<void()> printThird) {
std::unique_lock<std::mutex> l(mtx);
cv.wait(l, [this] {return (mfirst && msecond) == true; });
printThird();
}
};
int main()
{
Foo t;
std::thread t3((&Foo::third, t, printThird));
std::thread t2((&Foo::second, t, printSecond));
std::thread t1((&Foo::first, t, printFirst));
t3.join();
t2.join();
t1.join();
return 0;
}
猜猜我的输出是什么?它打印ThirdSecondFirst。
这怎么可能?这段代码是不是容易出现死锁?我的意思是,当第一个线程在函数second 中获取互斥锁时,它不会永远等待,因为现在获取互斥锁后,我们无法更改变量mfirst?
【问题讨论】:
-
cv.wait()unlocks the mutex 在等待时,允许另一个线程获取它 -
感谢@RemyLebeau,现在我明白它不会导致死锁。但是它怎么能在所有这些之前调用第三呢? cv 不应该等待布尔值变为真吗?
-
您的代码没有调用
cv.notify_all()或cv.notify_one()来通知等待线程cv已发出信号,以便它们可以停止等待并重新获取互斥锁以检查其谓词条件。致电mfirst = true;和msecond = true;后,您需要通知cv。在没有cv.notify_...()的情况下调用cv.wait()完全违背了使用conditional_variable的全部目的 -
仍然,我无法理解线程是如何通过这一行的:cv.wait(l, [this] {return (mfirst && msecond) == true; });
-
阅读我在之前评论中链接到的文档。
标签: c++ concurrency synchronization mutex deadlock