多线程线程管理
多线程中引用
使用引用一般是不安全的,简单的使用,可能就是纯粹的赋值。
1.std::ref()
引用的可以使用std::ref()来进行引用传递,但是不推荐。
#include<iostream>
#include<thread>
#include<string>
class Factor {
public:
void operator()(std::string& msg) {
std::cout << "factor msg:" << msg << std:: endl;
msg = "i love you";
}
};
int main(int argc, char** argv)
{
std::string msg = "i love t1";
std::thread t1((Factor()), std::ref(msg));
t1.join();
std::cout << "main msg:" << msg << std::endl;
return 0;
}
2. std::move()
线程一般是唯一的,不能出现赋值的情况,比如这种
std::thread t2 = t1;
但是可以使用std::move()进行移动。移动后之前的就为空,所以这里使用t2.join()
比如:
#include<iostream>
#include<thread>
#include<string>
class Factor {
public:
void operator()(std::string& msg) {
std::cout << "factor msg:" << msg << std:: endl;
msg = "i love you";
}
};
int main(int argc, char** argv)
{
std::string msg = "i love t1";
std::thread t1((Factor()), std::ref(msg));
std::thread t2 = std::move(t1);
t2.join();
std::cout << "main msg:" << msg << std::endl;
return 0;
}
3. 常用
- 使用get_id()获取pid
std::cout << std::this_thread::get_id() << std::endl;
std::cout << t2.get_id() << std::endl;
2、std:🧵:hardware_concurrency()获取最大线程数
int num = std::thread::hardware_concurrency();
std::cout << num << std::endl;
mutex
如果像这样写代码,输出就是混乱的
#include<iostream>
#include<thread>
#include<mutex>
void fun1()
{
for (int i= 0;i<50;i++)
{
std::cout << "fun1 id" << i << std::endl;
}
}
int main(int argc,char** argv)
{
std::thread t1(fun1);
for (int i = 0; i < 50; i++)
{
std::cout << "main id" << i << std::endl;
}
if (t1.joinable()) {
t1.join();
}
return 0;
}
为了解决上述的问题一般要对cout加上锁
1.最简单的方法,这种方法直接使用lock()和unlock(),但是这种方式至少存在两种问题:1)其他线程可能也会使用到cout,这种情况并不互斥 2)如果在lock()后面的过程出现错误,可能出现不能使用cout,也不会释放资源的情况。
#include<iostream>
#include<thread>
#include<mutex>
#include<string>
std::mutex mu;
void share_print(std::string msg,int id)
{
mu.lock();
std::cout << msg << " " << id << std::endl;
mu.unlock();
}
void fun1()
{
for (int i= 0;i<50;i++)
{
share_print("fun1 id", i);
}
}
int main(int argc,char** argv)
{
std::thread t1(fun1);
for (int i = 0; i < 50; i++)
{
share_print("main id", i);
}
if (t1.joinable()) {
t1.join();
}
return 0;
}
2. std::lock_guardstd::mutex
最简单的使用,这种并不能完全的保护cout,cout还可能在别的地方被使用。
#include<iostream>
#include<thread>
#include<mutex>
#include<string>
std::mutex mu;
/*
void share_print(std::string msg,int id)
{
mu.lock();
std::cout << msg << " " << id << std::endl;
mu.unlock();
}
*/
void share_print(std::string msg, int id)
{
std::lock_guard<std::mutex> guard(mu);
std::cout << msg << " " << id << std::endl;
}
void fun1()
{
for (int i= 0;i<50;i++)
{
share_print("fun1 id", i);
}
}
int main(int argc,char** argv)
{
std::thread t1(fun1);
for (int i = 0; i < 50; i++)
{
share_print("main id", i);
}
if (t1.joinable()) {
t1.join();
}
return 0;
}
推荐这种方式锁,这种方式通过保护可控的f实现(这里f可以是任意的,比如这里使用的输出流)互斥资源的保护。
要注意的是1)不要自己写其他的东西改变这个层级对f的保护 2)不要将f作为参数返回出去了
#include<iostream>
#include<thread>
#include<mutex>
#include<string>
#include<fstream>
//std::mutex mu;
/*
void share_print(std::string msg,int id)
{
mu.lock();
std::cout << msg << " " << id << std::endl;
mu.unlock();
}
*/
/*
void share_print(std::string msg, int id)
{
std::lock_guard<std::mutex> guard(mu);
std::cout << msg << " " << id << std::endl;
}
*/
class LofFile
{
public:
LofFile() {
f.open("log.txt");
}
void share_print(std::string msg,int id) {
std::lock_guard<std::mutex> guard(m_mutex);
f << msg << " " << id << std::endl;
}
~LofFile() {
f.close();
}
private:
std::mutex m_mutex;
std::ofstream f;
};
void fun1(LofFile& log)
{
for (int i= 0;i<50;i++)
{
log.share_print("fun1 id", i);
}
}
int main(int argc,char** argv)
{
LofFile log;
std::thread t1(fun1,std::ref(log));
for (int i = 0; i < 50; i++)
{
log.share_print("main id", i);
}
if (t1.joinable()) {
t1.join();
}
return 0;
}