使用std :: condition_variable的函数的同步调用

问题描述 投票:2回答:1

我再次沉迷于学习并发并试图解决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

这怎么可能?该代码是否容易出现DEADLOCK?我的意思是,当第一个线程在函数second中获取互斥量时,它不会永远等待,因为现在当获取互斥量时,我们无法更改变量mfirst

c++ concurrency synchronization mutex deadlock
1个回答
0
投票

您有一个非常微妙的错误。

std::thread t3((&Foo::third, t, printThird));

此行不符合您的期望。它仅用一个参数printThird初始化线程,而不用您指定的3个参数初始化。那是因为您不小心使用了comma expression。结果,&Foo::thirdt只是被丢弃,成员函数甚至都不会被调用。

您的代码中唯一被调用的函数是printFirstprintSecondprintThird。没有任何同步,它们可以按任意顺序打印。您甚至可以得到交错输出。

作为旁注,如注释中所述,您使用的条件变量错误。

© www.soinside.com 2019 - 2024. All rights reserved.