美文网首页
线程传参详解

线程传参详解

作者: 是你亮哥哥呀 | 来源:发表于2019-08-28 23:46 被阅读0次

一、传递临时对象作为线程参数

  1. 只要使用临时构造的A类对象作为参数传递给线程,那么就一定能够再主线程执行完毕前把线程函数的第二个参数构造出来,从而确保即使detach,线程也能安全运行
  2. 若传递int这种简单类型参数,建议都是值传递,不要用引用,绝对不能用指针。防止节外生枝。
  3. 如果传递类对象,避免隐式转换。全部都在创建线程这一行就构建出临时对象,然后在函数里,用引用来接,否则会造成浪费。(用引用会构造两次,不用引用会构造三次)
  4. 即便用引用,编译器也默认用copy方式,除非显式地告诉编译器

建议不适用detach(),只是用join(),这样就不存在局部变量失效导致线程对内存的非法引用问题。

二、临时参数作为线程参数继续讲

  1. 线程id概念
    每个线程实际上都对应一个数字,可以用std::thread::get_id()获取
  2. 临时对象构造时机捕捉
#include <iostream>
#include <thread>
#include <string>
using namespace std;

class A {
public:
    A(int n) : m_number(n){
        cout << "constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    A(const A& a) {
        cout << "copy constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    ~A() {
        cout << "deconstructor" << endl;
    }
private:
    int m_number;
};

void myprint(const A &pa) {//用引用接收,copy 构造函数依然会执行,但是如果不用引用,会调用两次拷贝构造函数
                           //并且第二次拷贝是由子线程完成,可能会存在问题,故建议使用以用接收
    cout << "child thread address = " << &pa << ", child thread id = " << std::this_thread::get_id() << endl;
}

int main() {
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    int n = 8;
    //thread mythread(myprint, n); //隐式转换
    thread mythread(myprint, A(n)); //临时对象,子线程函数的参数都在主线程中构造
    
    //mythread.join(); //阻塞主线程
    mythread.detach(); //主线程和子线程分离
    
    cout << "主线程结束!" << endl;
    
    return 0;
}
传递临时对象,临时对象的构造时机

三、传递类对象、智能指针作为线程参数

  1. 如果要传递类对象引用,std::ref()显式地告诉编译器,传一个引用到子线程中去
#include <iostream>
#include <thread>
#include <string>
using namespace std;

class A {
public:
    A(int n) : m_number(n){
        cout << "constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    A(const A& a) {
        cout << "copy constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    ~A() {
        cout << "deconstructor" << endl;
    }
private:
    int m_number;
};

void myprint(const A &pa) {//用引用接收,copy 构造函数依然会执行,但是如果不用引用,会调用两次拷贝构造函数
                           //并且第二次拷贝是由子线程完成,可能会存在问题,故建议使用引用接收
    cout << "child thread address = " << &pa << ", child thread id = " << std::this_thread::get_id() << endl;
    //cout<< "the m_number of pa in child thread is "<<endl;
}

int main() {
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    int n = 8;
    //thread mythread(myprint, n); //隐式转换
    A myobj(n);

    //thread mythread(myprint, myobj); //临时对象,子线程函数的参数都在主线程中构造
    thread mythread(myprint, std::ref(myobj)); //临时对象,显式地告诉编译器,传一个引用到子线程中去
    
    mythread.join(); //阻塞主线程
    //mythread.detach(); //主线程和子线程分离
    
    cout << "主线程结束!" << endl;
    
    return 0;
}
传递类对象
  1. 传递智能指针,std::move()
#include <iostream>
#include <thread>
#include <string>
using namespace std;

void myprint2(unique_ptr<int> p) {
    cout << "child thread ptr address is " << p << ", child thread id = " << std::this_thread::get_id() << endl;
}

int main() {
    cout << "main thread id = " << std::this_thread::get_id() << endl;

    unique_ptr<int> myp(new int(100));
    cout << "main thread ptr address is " << myp << endl;
    thread mythread(myprint2, std::move(myp)); //智能指针
    mythread.join(); //用指针,只能用join()

    cout << "主线程结束!" << endl;
    
    return 0;
}
image.png

四、用成员函数指针做线程参数

#include <iostream>
#include <thread>
#include <string>
using namespace std;

class A {
public:
    A(int n) : m_number(n){
        cout << "constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    A(const A& a) {
        cout << "copy constructor, address = " << this << ", thread id = " << std::this_thread::get_id() << endl;
    }
    ~A() {
        cout << "deconstructor" << endl;
    }
    void print(int num) {
        cout << "child thread address is " << this << ", child thread id = " << std::this_thread::get_id() << endl;
    }
private:
    int m_number;
};

void myprint(const A &pa) {//用引用接收,copy 构造函数依然会执行,但是如果不用引用,会调用两次拷贝构造函数
                           //并且第二次拷贝是由子线程完成,可能会存在问题,故建议使用引用接收
    cout << "child thread address = " << &pa << ", child thread id = " << std::this_thread::get_id() << endl;
    //cout<< "the m_number of pa in child thread is "<<endl;
}

int main() {
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    int n = 8;
    
    A myobj(n);

    thread mythread(&A::print, &myobj, 10);
    mythread.join(); //阻塞主线程
    //mythread.detach(); //主线程和子线程分离
    
    cout << "主线程结束!" << endl;
    
    return 0;
}
image.png

相关文章

  • iOS多线程之pthread的简单使用

    前言 pthread是c语言编写的,基本用不到,了解一下就好. 线程创建代码 传参:C语言传参 oc传参

  • 2018-05-08

    多线程 初级概念与传参 join deatch 原子变量 互斥锁 与 线程安全 线程安全 多线程访问冲突 冲突...

  • Day16.参数传递(token传递,接口关联等)

    1. 传递变量说明1.1 传参方式1.1.1 内置变量1.1.2 函数助手1.2 传参形式1.2.1 同线程组1....

  • iOS进程间通信

    线程间通信 :通过performSelector系列的方法 可以实现 各种线程间的通信(通信 :调用与传参)进程间...

  • 多线程传参问题

    多线程传参,分为两种方式。一种是设置 ==全局变量==;另一种是通过int pthread_create((pth...

  • python子线程传参

    背景说明 今天在做python子线程调用时发现如下异常: 源代码书写如下: devId就是传入的参数,值为:06c...

  • jmeter跨线程传参

    在实际应用中,往往想要将上一个线程的数据给下一个线程用,如token。要实现跨线程传递参数,那么需要先用正则提取出...

  • jmeter跨线程传参

  • 线程传参详解

    一、传递临时对象作为线程参数 只要使用临时构造的A类对象作为参数传递给线程,那么就一定能够再主线程执行完毕前把线程...

  • C++ 并发编程学习(三)

    向线程函数传递参数 一. 传参const char*   函数f需要一个 std::string 对象作为第二个参...

网友评论

      本文标题:线程传参详解

      本文链接:https://www.haomeiwen.com/subject/rlomectx.html