我试图在一个类中运行两个并发线程,它们都使用相同的函数打印数据。使用 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!
我做错了什么?
最佳答案
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
互斥量在循环迭代开始时被获取。它会一直保留到迭代结束,然后立即再次抓取它,为其他线程潜入并获取互斥体留下一个非常小的窗口。
通过插入另一个代码块来从受锁保护的代码块中删除 sleep :
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 线程 2 线程 1 线程 2 线程”序列。没有什么可以阻止 2 线程在 1 线程之前唤醒并获取互斥锁,反之亦然。如果您想要完美的排序,请查看 std::condition_variable
。
关于C++ 类内线程并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76150930/