多线程学习记录1

网易云课堂上有门c++多线程的入门教程,学习过程在此记录下。

并发编程:

1.多进程(通信:文件,管道,消息队列);2.多线程(通信:共享内存)。

code1:

#include 
#include 
void test_funtion(){
	std::cout << "test test test!" <	std::thread t1(test_funtion);
	//t1.join();//main线程等待t1线程完成后继续向下执行
	t1.detach();//t1还没来得及输出,主程序就结束了,所以没有输出。线程detach之后,不能再join。
	if (t1.joinable()){
		t1.join();
	}
	return 0;
}
code2:

#include 
#include 
void test_funtion(){
	std::cout << "test_funtion!" <	std::thread t1(test_funtion);
	for (int i = 0; i < 100;++i)
	{
		std::cout << "main count i:" <	}
	t1.join();
	return 0;
}
如果在for循环中,程序抛出异常,那程序是否会直接结束了,不会执行join?

#include 
#include 
void test_funtion(){
	std::cout << "test_funtion!" << std::endl;
}
int main()
{
	std::thread t1(test_funtion);
	try
	{
		for (int i = 0; i < 100; ++i)
		{
			std::cout << "main count i:" << i << std::endl;
		}
	}
	catch (...)//捕获所有异常
	{
		t1.join();
		throw;//抛出异常
	}
	
	t1.join();
	return 0;
}
code3:

用对象初始化线程

#include 
#include 
class Test{
public:
	void operator()(){//重载函数调用运算符
		for (int j = 0; j < 100; ++j){
			std::cout << "object test j:" << j<
输出杂乱无章。
#include 
#include 
#include 
class Test{
public:
	void operator()(const std::string& temp){//重载函数调用运算符
		for (int j = 0; j < 100; ++j){
			std::cout << temp +"object test j:" << j<
	unsigned num_cpus = std::thread::hardware_concurrency();//获取cpu core个数
	std::cout << "num_cpus " << num_cpus << std::endl;	
	t1.join();
	return 0;
}
构造线程时,若参数为引用类型,需要使用std::ref,使用&是没有效果的。

code4:

数据互斥和竞争

#include 
#include 
void test_funtion(){
	for (int i = 0; i < 100; ++i)
	{
		std::cout << "test_funtion count i:" << i << std::endl;
	}
}
int main()
{
	std::thread t1(test_funtion);
	for (int i = 0; i < 100; ++i)
	{
		std::cout << "main count i:" << i << std::endl;
	}
	t1.join();
	return 0;
}
输出很乱,因为t1线程和主线程都在使用cout资源会发生竞争。
#include 
#include 
#include 
#include 
std::mutex mu;
void print(std::string s, int i){
	mu.lock();
	std::cout << s <<"count i:"<< i << std::endl;
	mu.unlock();
}
void test_funtion(){
	for (int i = 0; i < 100; ++i)
	{
		print("test_funtion ", i);
	}
}
int main()
{
	std::thread t1(test_funtion);
	for (int i = 0; i < 100; ++i)
	{
		print("main ", i);
	}
	t1.join();
	return 0;
}
加锁后,可以看到,输出很有次序。cout的访问权限是通过mu来同步的,两个线程不会同时访问cout,只要两个线程都是通过print函数打印的,那么就不会出现上面次序混乱问题。这里面,若
std::cout << s <<"count i:"<< i << std::endl;
发生异常,那么mu就会一直锁住,故使用lock和unlock要小心。可以使用省事的方法:lock_guard。
void print(std::string s, int i){
	std::lock_guard  lg(mu);
	//mu.lock();
	std::cout << s <<"count i:"<< i << std::endl;
	//mu.unlock();

}
只要lg构造时为mu上锁,析构时解锁,因为lg是局部变量,出大括号就析构了,所以即使有异常也会正常解锁。还有问题:cout是全局的,其他线程在不加锁的情况下就可以使用,mu保护cout还是力不从心的。
code 5:
#include 
#include 
#include 
#include 
#include 
std::mutex mu;
class LogFile{
public:
	LogFile(){
		f.open("log.txt");
	}
	void log(std::string s, int i){
		std::lock_guard lg(m_mutex);
		f << s << " count i:" << i << std::endl;
	}
protected:
private:
	std::mutex m_mutex;//保护f
	std::ofstream f;
};
void test_funtion(LogFile& lf){
	for (int i = 0; i < 100; ++i)
	{
		lf.log("test_funtion ", i);
	}
}
int main()
{
	LogFile logFile;
	std::thread t1(test_funtion,std::ref(logFile));
	for (int i = 0; i < 100; ++i)
	{
		logFile.log("main ", i);
	}
	t1.join();
	return 0;
}
这样比code4有改善,要想使用f,必须使用LogFile类,在类里面f又是被m_mutex保护的,所以是线程安全的。





你可能感兴趣的:(c++多线程入门)