zoukankan      html  css  js  c++  java
  • [c++_thread] 对于thread中join,detach以及joinable讲解

    2020/8/15

    标签(空格分隔):二零二零八月


    今天主要是进行线程的学习

    线程(std::thread)

    我是直接从cpp官方文档进行thread库的学习。
    std::thread的简介时候,能够知道
    std::thread
    Member types

    • id //thread id
    • native_handle_type //Native handle type

    Member functions

    • (constructor) //construct thread
    • (destructor) //Thread destructor
    • operator= //Move-assign thread
    • get_id //Get thread id
    • joinable //Check if joinable(可结合的)稍后解释可结合的意思
    • join //join thread
    • detach //Detach thread
    • swap //swap threads
    • native_handle //Get native handle
    • hardware concurrency[static] // detect hardware concurrency

    non-member overloads

    • swap(thread) // Swap threads(function)

    因为类数据成员我们看注释都可以读懂相关的含义,所以直接上相关的成员函数

    先是初始化
    我们在初始化直接使用

    std::thread name (function)这样的格式即可,如果我们不用后面的小括号的话,只进行线程的命名,那么就是进行了默认初始化

    而在后面对的成员函数中,我先介绍Joinable,因为这个和其他成员函数更有连接性,介绍了joinable以后更好进行其他的成员函数的理解。

    joinable

    joinabe成员函数的作用在c++官方文档中是返回线程是否是可结合的。
    可结合的意思就是,一个线程是否能够被执行Join或者是detch操作,因为相同的线程不能被join两次,也不能join完再进行detach,同理也不可以被detach两次,所以joinable函数就是判断是否能进行可结合。
    在c++的官方文档中列出了不能被joinable的情况。

    • 是被默认构造的(即没有小括号的构造语句)std::thread name;
    • 执行过move操作
    • 执行过join或者detach

    以下展示一个实例

    #include <iostream>       // std::cout
    #include <thread>         // std::thread
     
    void mythread() 
    {
      // do stuff...
    }
     
    int main() 
    {
      std::thread foo;//这里就是上述提到的没有小括号的构造语句,使用的是默认初始化
      std::thread bar(mythread);
    
      std::cout << "Joinable after construction:\n" << std::boolalpha;
      std::cout << "foo: " << foo.joinable() << '\n';//这里会输出false
      std::cout << "bar: " << bar.joinable() << '\n';//这里输出true
    
      if (foo.joinable()) foo.join();//不会进行join操作
      if (bar.joinable()) bar.join();//会进行join操作
    
      std::cout << "Joinable after joining:\n" << std::boolalpha;
      std::cout << "foo: " << foo.joinable() << '\n';//这里输出false
      std::cout << "bar: " << bar.joinable() << '\n';//这里也会输出false,因为已经进行了一次join操作
    
      return 0;
    }
    

    既然上面讲提到了join以及detach,那么接下来自然就要进行join与detach的讲解

    join与detach

    join在从c++官方文档的介绍中,我们可以知道,join是用来进行同步的一个工具,当我们在主进程中使用join了一个子进程,那么我们主进程就要等待这个子进程运行完毕,并且回收子进程的资源后,再执行主进程的程序。
    以下是测试代码

    #include<iostream>
    #include<thread>
    
    void thread_function() {
    
    		std::cout << "thread function excuting" << std::endl;
    }
    
    int main()
    {
    	std::thread threadObj(thread_function);
    
    	threadObj.join();
    	std::cout << "I am Main function" << std::endl;
    	std::cout << "Exit of Main function" << std::endl;
    
    	system("pause");
    	return 0;
    }
    
    

    最后输出的结果
    threadJoin
    我们可以看到其中是一步步的执行,那么我们会不会有个疑惑这样执行好像没有用到进程,就是调用。那么这个时候我们可以使用get_id获取线程的id,我们使用std::this_thread::get_id(),就可以获取到相应的进程id,然后得到以下的输出。
    get_id
    我们可以看到进程的id是不一样,说明我们是成功的控制了进程的运行。
    而在我删除掉了join试图运行时,我发现它是按照不同顺序来进行的,但是运行到最后会出现abort() has been called,我去搜查了相关资料发现,join以后会表示这个线程可以destroy了,那么在子线程结束后会进行相关资源的回收,但是如何没有join或者detach,就会导致不会产生标记,在最后整个进程结束时,该回收的资源没有回收,就会产生错误。
    那么detach呢,我们先从detach的字面意思进行理解下,detach指的是分离,脱离的意思,那么我们引申过来,在线程中的话,detach的意思就是将主线程和子线程进行分离,主线程是不会再等待子线程。
    那么这个时候会有一个疑问,就是主线程结束的时候,进程也就结束,那么是不是表示子线程也是结束。结果不是,子线程的输出只是不进行显示,它还是会运行完,再被回收。
    以下为detach代码

    
    #include<iostream>
    #include<thread>
    
    void thread_function() {
    
    		std::cout << "thread function excuting"<<"\n"<<std::this_thread::get_id() << std::endl;
    		std::cout << "thread function excuting1" << "\n"  << std::endl;
    		std::cout << "thread function excuting2" << "\n" << std::endl;
    	}
    
    int main()
    {
    	std::thread threadObj(thread_function);
    	threadObj.detach();
    	std::cout << "I am Main function" << "\n"<<std::this_thread::get_id()<<std::endl;
    	std::cout << "I am Main function1" << "\n" << std::endl;
    	std::cout << "I am Main function2" << "\n" << std::endl;
    	std::cout << "I am Main function3" << "\n" << std::endl;
    	std::cout << "Exit of Main function" << std::endl;
    
    	return 0;
    }
    
    

    detach
    我们可以看到detach后,输出是交叉进行的。

    参考资料

    http://www.cplusplus.com/reference/thread/thread/

  • 相关阅读:
    CSS(22)CSS的长度单位
    CSS(21)CSS Grid网格布局
    CSS(20)CSS3 弹性盒子(Flex Box)
    CSS(19)CSS3 多列
    CSS(18)CSS3 过渡与动画
    CSS(17)CSS 2D、3D 转换
    CSS(16)CSS3 渐变(Gradients)
    CSS(15)CSS媒体查询Media Queries
    CSS(14)CSS 伪元素
    CSS(13)CSS 伪类(Pseudo-classes)
  • 原文地址:https://www.cnblogs.com/Yekko/p/13508941.html
Copyright © 2011-2022 走看看