C++11的多线程并发编程(二)

C++11的多线程并发编程(二)

疫情已到确诊3w+,望早日结束这疫情。
根据上一节学习的的线程概念,开始进一步学习C++11新标准的多线程编程,C++11引入了5个头文件,分别是:atomic, thread, mutex, condition_variable, future。主要包含互斥类,条件变量,同步线程和异步线程等的相关类,这一节主要记录thread头文件的相关内容。

  1. 线程的创建std::thread
    std::thread的构造函数主要有三种:不带参数的构造函数,初始化构造函数,移动构造函数。写个代码举个栗子:
#include <iostream>
#include <thread>
#include <unistd.h>

using namespace std;
void myFunc1()
{	
	cout << "hello comedy" << endl;
}
void myFunc2(int i)
{
	cout << "hello comedy" << i << endl;
}
int main(int argc, char *argv[])
{
	int i = 99;
	thread t1(myFunc1);
	thread t2(myFunc2,i);
	thread t3(myFunc3,i);
	thread t4(move(t3));

	sleep(1);
	cout << "the main thread is end;" << endl;
	
	return 0;
}

sleep(1)让主线程睡眠一秒钟,子线程有足够的时间去运行,因为进程是否执行完毕,取决于主线程是否执行结束。如主线程结束但子线程没有时间执行,则会被操作系统强制结束。

  1. 线程的阻塞 join()

在thread类中提供了一个函数join();表示线程的加入和回合,其作用与sleep(n)等价,用来阻塞主线程,让主线程等到子线程执行完毕。用法如例:

#include <iostream>
#include <thread>

using namespace std;

void myFunc(char *str)
{
	cout << "hello " << str << endl;
}

int main(int argc, char *argv[])
{
	char str[] = "comedy!";
	thread t1(myFunc , str);
	t1.join();
	cout << "the main thread is endl;" << endl;
	return 0;
}

一个良好的程序是应该是主线程等待子线程执行完毕后,自己再结束。但thread类提供了一个成员函数detach()使得,子线程和主线程自己运行自己的,且无需等待。

  1. 线程分离detach()
    线程分离,子线程对象调用detach成员函数,使得子线程失去与主线程的关联,此时主线程结束而子线程未结束,子线程被后台C++运行库接管,分离线程即守护线程,或是缓存清理任务,或是监视文件任务。这里借鉴某个例子证明一个问题。
    在Ubuntu系统指定文件目录中编写c++程序文件。
    在这里插入图片描述
#include <iostream>
#include <thread>

using namespace std;

class myTest
{
	public:
		int parameter;
		myTest(int i): parameter(i){}
		void operator()()
		{
			cout << "my thread is createed" << endl;
			cout << "my parameter is :" << parameter << endl;
			//do something.....
			cout << "my thread is end" << endl;
			
		}
};

int main(int argc, char *argv[])
{
	int x = 99;
	myTest test(x);
	thread mythread(test);
	mythread.detach();
	
	cout << "the main thread is end " << endl;
	return 0;
	
}

然后通过命令执行编译链接库 g++ 8.5.cpp -o 8.5 -pthread -std=c++11
并通过命令执行 ./8.5 结果如图所示:
在这里插入图片描述
从图中可以看出,main线程很早就结束了,但是子线程还在执行,但是主线程的结束会这个test对象就会被销毁,那子线程的对象哪来的。通过修改案例代码:增加类的构造函数和拷贝构造函数和虚构函数。

#include <iostream>
#include <thread>

using namespace std;

class myTest
{
	public:
		int parameter;
		myTest(int i): parameter(i)
		{
			cout << "myTest's createFunction is running" << endl;
		}
		myTest(const myTest &test): parameter(test.parameter)
		{
			cout << "myTest's copyFunction is running" << endl;
		}
	
		~myTest()
		{
			cout << "myTest's removeFunction is running" << endl;
		}
		void operator()()
		{
			cout << "my thread is createed" << endl;
			cout << "my parameter is :" << parameter << endl;
			//do something.....
			cout << "my thread is end" << endl;
			
		}
};

int main(int argc, char *argv[])
{
	int x = 99;
	myTest test(x);
	thread mythread(test);
	mythread.detach();
	
	cout << "the main thread is end " << endl;
	return 0;
	
}

运行结果如图所示:

在这里插入图片描述
结果显示第一个析构的对象实际上是被赋值进线程中的,执行完主线程主线程的对象被析构,当子线程执行结束时再调用析构函数。

下一节继续学习线程传参部分。

发布了2 篇原创文章 · 获赞 0 · 访问量 114

猜你喜欢

转载自blog.csdn.net/COMEDY_lang/article/details/104219660