C++ 监控互斥线程问题

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

这段代码应该停在 15 个字符(行)处,但事实并非如此,它会无限地继续下去。这段代码的主要问题是条件变量逻辑不允许所有线程识别何时达到目标 max_count 15,导致程序无限期运行。

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>

using namespace std;

class Monitor
{
private:
    string line = "";
    mutex mtx;
    condition_variable cv;
    int vowel_count = 0;
    int max_count = 0;

public:
    void AddA(char symbol)
    {
        unique_lock<mutex> lock(mtx);
        cv.wait(lock, [this] { return vowel_count < 3; });
        line += symbol;
        vowel_count++;
        max_count++;
        cv.notify_all();
    }

    void AddBC(char symbol)
    {
        unique_lock<mutex> lock(mtx);
        cv.wait(lock, [this] { return vowel_count >= 3; });
        line += symbol;
        max_count++;
        vowel_count = 0;
        cv.notify_all();
    }

    string getLine()
    {
        unique_lock<mutex> lock(mtx);
        return line;
    }

    int getVowelCount()
    {
        unique_lock<mutex> lock(mtx);
        return vowel_count;
    }

    int getMaxCount()
    {
        unique_lock<mutex> lock(mtx);
        return max_count;
    }
};

void First(Monitor& monitor)
{
    while (true)
    {
        monitor.AddA('A');

        if (monitor.getMaxCount() == 15)
        {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Second(Monitor& monitor)
{
    while (true)
    {
        monitor.AddBC('B');

        if (monitor.getMaxCount() == 15)
        {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Third(Monitor& monitor)
{
    while (true)
    {
        monitor.AddBC('C');

        if (monitor.getMaxCount() == 15)
        {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Print(Monitor& monitor)
{
    while (true)
    {
        cout << monitor.getLine() << endl;

        if (monitor.getMaxCount() == 15)
        {
            break;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

int main()
{
    Monitor monitor;

    thread t1(First, ref(monitor));
    thread t2(Second, ref(monitor));
    thread t3(Third, ref(monitor));
    thread t4(Print, ref(monitor));

    t1.join();
    t2.join();
    t3.join();
    t4.join();

    return 0;
}

我尝试过各种方法,例如将数量更改为大于或等于 15,但它进一步破坏了它。

c++ multithreading mutex linear-programming
1个回答
0
投票

ALX23z 感谢您的解释我调整了我的代码,现在它可以工作了

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>

using namespace std;

class Monitor
{
private:
    string line = "";
    mutex mtx;
    condition_variable cv;
    int vowel_count = 0;
    int max_count = 0;

public:
    void AddA(char symbol)
    {
        unique_lock<mutex> lock(mtx);
        cv.wait(lock, [this] { return vowel_count < 3; });

        if (max_count >= 15)
        {
            return;
        }

        line += symbol;
        vowel_count++;
        max_count++;
        cv.notify_all(); 
    }

    void AddBC(char symbol)
    {
        unique_lock<mutex> lock(mtx);
        cv.wait(lock, [this] { return vowel_count >= 3; });

        if (max_count >= 15)
        {
            return;
        }

        line += symbol;
        max_count++;
        vowel_count = 0;
        cv.notify_all();
    }

    string getLine()
    {
        unique_lock<mutex> lock(mtx);
        return line;
    }

    int getVowelCount()
    {
        unique_lock<mutex> lock(mtx);
        return vowel_count;
    }

    int getMaxCount()
    {
        unique_lock<mutex> lock(mtx);
        return max_count;
    }
};

void First(Monitor& monitor)
{
    while (true)
    {
        if (monitor.getMaxCount() >= 15)
        {
            break;
        }

        monitor.AddA('A');

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Second(Monitor& monitor)
{
    while (true)
    {
        if (monitor.getMaxCount() >= 15)
        {
            break;
        }
        monitor.AddBC('B');

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Third(Monitor& monitor)
{
    while (true)
    {
        if (monitor.getMaxCount() >= 15)
        {
            break;
        }

        monitor.AddBC('C');

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void Print(Monitor& monitor)
{
    while (true)
    {
        cout << monitor.getLine() << endl;

        if (monitor.getMaxCount() >= 15)
        {
            break;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

int main()
{
    Monitor monitor;

    thread t1(First, ref(monitor));
    thread t2(Second, ref(monitor));
    thread t3(Third, ref(monitor));
    thread t4(Print, ref(monitor));

    t1.join();
    t2.join();
    t3.join();
    t4.join();

    cout << "Done" << endl;
    cout << monitor.getLine() << endl;

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.