多线程线程管理

多线程中引用

使用引用一般是不安全的,简单的使用,可能就是纯粹的赋值。

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. 常用

  1. 使用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;
}
posted @ 2020-07-30 21:20  cyssmile  阅读(298)  评论(0编辑  收藏  举报