C++并发与多线程(一)thread

1. 语法

头文件为<thread>

thread是一个线程类,可以用来生成对象并运行该线程 thread t1(function)

此时子线程t1 依附于主线程,主线程结束后子线程也会结束

t1.join() 让主线程等待子线程结束后再继续运行

t1.detach() 分离主线程与子线程,主线程结束后子线程依然可以运行

this_thread::get_id() 查询当前线程id

2. 对象作为线程参数

thread t1(function, A(1)) 类A生成一个临时对象传入线程中,此时会在主线程内调用默认构造、拷贝构造、析构函数。若子线程以

引用方式接受对象,则在子线程中只调用一次析构函数。

thread t1(function, 1) 将1作为参数传入线程,则会在子线程中调用默认构造函数与析构函数,此时如果没有调用join() 函数,很

可能主线程提前结束,子线程无法调用构造函数导致出错。

A aa(1); thread t1(function, aa) 将主线程中构造的对象传入线程,则首先会在主线程中调用默认构造函数构建aa,接着在主线程

中调用拷贝构造函数将aa拷入子线程,并在子线程中执行析构函数,最后在主线程中执行析构函数回收aa。

注意:以上例子默认使用引用传递,若是值传递,则在子线程中会增加一次拷贝构造函数调用

虽然形式上以引用方式传递,但还是会调用拷贝构造函数,所以子线程中的对象地址和主线程的不同

若想要真正的实现引用传递,需使用ref()函数,如A aa(1); thread t1(function, ref(aa))

注意:ref()函数不能作用于临时对象,因为临时对象在使用后会被销毁

如果想要更改const类型的对象数据,可在对象的成员数据前加mutable关键字

3. 用成员函数指针做线程函数

thread mythread(&A::C, aa, 4); C为类A中成员函数,aa为A的对象,C有一个参数为4。

此时会在主线程中执行一次拷贝构造函数将aa拷贝至子线程,在子线程中执行析构函数

thread mythread(&A::C, ref(aa), 4) ==thread mythread(&A::C, &aa, 4)

上面两个语句效果相同,均不需要在主线程中调用拷贝构造函数,做到了真正的引用传递

注意:没有在主线程中调用拷贝构造函数,必须用join() 函数,因为主线程结束后无法调用拷贝构造

4. 智能指针作为参数传递

void myprint (unique_ptr<int> p) {} thread mythread(myprint, move(p1));

智能指针传递到子进程后,p关联了p1之前关联的指针,p1的指针转移到了p上,p1不关联指针

5. 创建和等待多个线程

创建多个线程,使用容器来存放线程,线程的入口统一使用myprint 函数

void myprint (int i) {
    cout << "这里是子线程" << ", id是" << std::this_thread::get_id() << endl;
}
int main()
{
     vector<thread> mythread;
     for (int i = 0; i < 10; ++i) {
        mythread.push_back(thread(myprint, i));
    }
     for (auto it = mythread.begin(); it != mythread.end(); ++it) {
         it->join();
     }
    cout << "hello world!" << endl;
    return 0;
}
运行的结果是乱序的,这与操作系统内部对线程的运行调度机制有关

![](https://secure2.wostatic.cn/static/nFAGHnycmaFghmSgtZKzJr/image.png)

**数据共享问题**

  有读有写的数据:读的时候不能写,写的时候不能读

  只读的数据:是安全稳定的,可以直接读取

测试代码
#include <iostream>
#include <thread>
#include <vector>
#include <memory>
using namespace std;

class A {
public:
    A(int a) : m_a(a) {
        cout << "在线程id:" << std::this_thread::get_id() << "中 执行默认构造函数" << endl;
    }
    A(const A& B) {
        m_a = B.m_a;
        cout << "在线程id:" << std::this_thread::get_id() << "中 执行拷贝构造函数" << endl;
    }
    void C(int c) {
        cout << "在线程id:" << std::this_thread::get_id() << "中 调用函数C" << endl;
    }
    void operator() (int k) {
        cout << "在线程id:" << std::this_thread::get_id() << "中 实现了小括号重载" << endl;
    }
    ~A() {
        cout << "在线程id:" << std::this_thread::get_id() << "中 执行析构函数" << endl;
    }
    mutable int m_a;
};

void myprint (int i) {
    cout << "这里是子线程" << ", id是" << std::this_thread::get_id() << endl;
}
int main()
{
     vector<thread> mythread;
     for (int i = 0; i < 10; ++i) {
        mythread.push_back(thread(myprint, i));
    }
     for (auto it = mythread.begin(); it != mythread.end(); ++it) {
         it->join();
     }
     cout << "hello world!" << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值