• 【C++11多线程】线程的创建、结束、传递参数


    1.普通函数作为线程函数

    程序运行起来,生成一个进程,其中主线程从 main() 函数开始执行,当主线程从 main() 函数返回,则整个进程执行完毕。也就是说,整个进程是否执行完毕的标志是主线程是否执行完毕。

    既然主线程从 main() 函数开始执行,那么我们自己创建的线程也需要从一个函数开始运行,一旦这个函数运行完毕,我们自己创建的线程也结束运行。

    1.1 thread

    头文件 #include

    thread 是一个类,thread td(myThread) 是利用构造函数创建了一个 thread 类对象 td,传入参数 myThread 是一个可调用对象。

    C++ 中的可调用对象可以是函数、函数指针、lambda表达式、bind创建的对象或者重载了函数调用运算符的类对象。

    1.2 join()

    join() 是 thread 类中的一个方法,其作用是:阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下执行。

    #include 
    #include 
    using namespace std;
    
    // 线程入口函数
    void myThread()
    {
    	cout << "myThread begin" << endl;
    	cout << "myThread running1" << endl;
    	cout << "myThread running2" << endl;
    	cout << "myThread running3" << endl;
    	cout << "myThread running4" << endl;
    	cout << "myThread running5" << endl;
    	cout << "myThread running6" << endl;
    	cout << "myThread end" << endl;
    	return;
    }
    
    int main()
    {
    	thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行
    
    	td.join(); // 阻塞主线程并等待myThread子线程执行完,当子线程执行完毕,这个join()函数就执行完毕,主线程继续往下执行
    
    	cout << "hello world1" << endl;
    	cout << "hello world2" << endl;
    	cout << "hello world3" << endl;
    	cout << "hello world4" << endl;
    	cout << "hello world5" << endl;
    	cout << "hello world6" << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    输出结果如下:

    在这里插入图片描述

    1.3 detach()

    detach() 是 thread 类中的一个方法,其作用是:一旦 detach() 之后,与主线程关联的 thread 对象就会失去与主线程的关联,此时这个子线程就会驻留在后台运行(守护线程),这个子线程就相当于被 C++ 运行时库接管了,当这个子线程执行完成后,由运行时库负责清理该线程的相关资源。

    一旦调用了 detach(),就不能再用 join() 了,否则系统会报异常。

    #include 
    #include 
    using namespace std;
    
    // 线程入口函数
    void myThread()
    {
    	cout << "myThread begin" << endl;
    	cout << "myThread running1" << endl;
    	cout << "myThread running2" << endl;
    	cout << "myThread running3" << endl;
    	cout << "myThread running4" << endl;
    	cout << "myThread running5" << endl;
    	cout << "myThread running6" << endl;
    	cout << "myThread end" << endl;
    	return;
    }
    
    int main()
    {
    	thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行
    
    	td.detach(); // 主线程可以不等子线程结束就先结束,子线程不会被强制结束,而是可以继续运行,驻留在后台,由C++运行时库接管
    
    	cout << "hello world1" << endl;
    	cout << "hello world2" << endl;
    	cout << "hello world3" << endl;
    	cout << "hello world4" << endl;
    	cout << "hello world5" << endl;
    	cout << "hello world6" << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    输出结果如下:

    在这里插入图片描述

    1.4 joinable()

    joinable() 是 thread 类中的一个方法,其作用是:判断线程是否可以成功使用 join() 或 detach()。

    • 如果返回 true,表示可以调用 join() 或 detach();
    • 如果返回 false,表示已经调用过 join() 或 detach(),不能再调用 join() 或 detach() 了。

    2.函数对象作为线程函数

    #include 
    #include 
    using namespace std;
    
    class A
    {
    public:
    	int m_i;
    
    	A(int i) : m_i(i)
    	{
    		cout << "构造函数执行,this = " << this << endl;
    	}
    	
    	A(const A& a) : m_i(a.m_i)
    	{
    		cout << "拷贝构造函数执行,this = " << this << endl;
    	}
    
    	~A()
    	{
    		cout << "析构函数执行,this = " << this << endl;
    	}
    	
    	// 线程入口函数
    	void operator()(int num)
    	{
    		cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
    	}
    };
    
    int main()
    {
    	int i = 100;
    	A a(i);
    
    	thread td(a, 18);
    	td.join();
    
    	cout << "hello world1" << endl;
    	cout << "hello world2" << endl;
    	cout << "hello world3" << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    输出结果如下:

    在这里插入图片描述

    3.lambda表达式作为线程函数

    #include 
    #include 
    using namespace std;
    
    int main()
    {
        // 线程入口函数
    	auto myThread = [] {
    		cout << "myThread begin" << endl;
    		cout << "myThread running1" << endl;
    		cout << "myThread running2" << endl;
    		cout << "myThread running3" << endl;
    		cout << "myThread running4" << endl;
    		cout << "myThread running5" << endl;
    		cout << "myThread running6" << endl;
    		cout << "myThread end" << endl;
    	};
    
    	thread td(myThread);
    	td.join();
    
    	cout << "hello world1" << endl;
    	cout << "hello world2" << endl;
    	cout << "hello world3" << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    输出结果如下:

    在这里插入图片描述

    4.类成员函数作为线程函数

    #include 
    #include 
    using namespace std;
    
    class A
    {
    public:
    	int m_i;
    	
    	A(int i) : m_i(i)
    	{
    		cout << "构造函数执行,this = " << this << endl;
    	}
    	
    	A(const A& a) : m_i(a.m_i)
    	{
    		cout << "拷贝构造函数执行,this = " << this << endl;
    	}
    
    	~A()
    	{
    		cout << "析构函数执行,this = " << this << endl;
    	}
    
    	// 线程入口函数
    	void work(int num)
    	{
    		cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
    	}
    };
    
    int main()
    {
    	A a(100);
    
    	thread td(&A::work, a, 18);
    	td.join();
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    输出结果如下:

    在这里插入图片描述

    5.向线程函数传递参数

    关于向线程函数传递参数的具体细节,可以看下这篇文章:https://www.cnblogs.com/chen-cs/p/13056703.html

  • 相关阅读:
    Debian的系统启动过程
    关系数据理论 规范化
    gitlab自动定时备份文件,备份失败发送邮件
    blob相关
    二维数组前缀和(JAVA)
    Matlab制作含随机缺陷的纳米颗粒(任何输入Data)
    postman测试接口使用
    pytorch的函数(如squeeze,permute,flatten,numel,matmul)
    Linux及其常用命令
    Elasticsearch:ingest pipeline 使用示例 - 解析常用日志格式
  • 原文地址:https://blog.csdn.net/qq_42815188/article/details/90166333