C++类内线程并发

sqougxex  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(153)

我试图在一个类中运行两个并发线程,它们都使用相同的函数打印数据。使用std::lock_guard进行作用域锁。问题是只有第一个线程被触发。永远不会调用第二个线程

#include <thread>
#include <string>
#include <iostream>
#include <mutex>

//global 
std::mutex m_printmutex;

class Class
{
public:
    Class(const std::string& s, const int& i) : m_data(s), threadName(i) { }
    ~Class() { 
        m_thread.join(); 
        m_thread2.join();
        }
    void runThread() { 
        m_thread = std::thread(&Class::print, this); 
        m_thread2 = std::thread(&Class::print,this);
    }

private:
    std::string m_data;
    std::thread m_thread;
    std::thread m_thread2;
    int threadName;
    void print()  { 
        
        while(1){
            std::lock_guard<std::mutex> lg(m_printmutex);
            std::cout << "thread # " << std::this_thread::get_id() << " "  << m_data << '\n'; 
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
        }
};

int main()
{
    Class c("Hello, world!",1);
    c.runThread();

}

从上述例子中可以明显看出。线程连接发生在析构函数中。
程序的输出如下:

thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!
thread # 140232348595776 Hello, world!

我做错了什么?

qhhrdooz

qhhrdooz1#

while(1){
            std::lock_guard<std::mutex> lg(m_printmutex); 
            std::cout << "thread # " << std::this_thread::get_id() << " "  << m_data << '\n'; 
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        } //mutex lock released here

互斥体在循环迭代开始时被抓取。它一直保持到迭代结束,然后立即再次抓取它,为其他线程留下一个非常小的窗口来潜入并获取互斥锁。
通过插入另一个代码块,从受锁保护的代码块中删除睡眠:

while(1){
            {
                std::lock_guard<std::mutex> lg(m_printmutex); 
                std::cout << "thread # " << std::this_thread::get_id() << " "  << m_data << '\n'; 
            } // mutex lock released here
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }

这给了另一个线程一整秒的时间来获取互斥量并完成它的工作。
注意:你仍然不能保证一个漂亮的,有序的“1-thread 2-thread 1-thread 2-thread”序列。没有什么可以阻止2线程在1线程之前唤醒并获取互斥量,反之亦然。如果您想要完美的排序,请查看std::condition_variable s。

相关问题