C++11并发学习之二:线程管理

1.启动线程

(1)使用对象

小试牛刀”中thread构造时传入的是函数,还可以传入对象。

#include <thread>
#include <iostream>

void func()
{
    std::cout<<"worker thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::cout<<"Hello Word"<<std::endl;

}

class MyFunc
{
public:
    //重载的函数操作符,对象使用起来就像对象是一个函数一样
    void operator()()//无参数无返回值
    {
        func();
    }
};

int main()
{
    std::cout<<"main thread ID:"<<std::this_thread::get_id()<<std::endl;
    MyFunc myFunc;//需先定义类的对象
    std::thread workerThread(myFunc);
    workerThread.join();
    return 0;
}

(2)使用参数

#include <thread>
#include <iostream>
#include <string>

void func(int i,std::string const &s)
{
    std::cout<<"worker thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::cout<<"Hello Word"<<" "<<s<<" "<<i<<std::endl;
}

int main()
{
    std::cout<<"main thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::string str="at";
    //注意这里第二个参数的写法
    //为何不直接传str:虽然函数func的第二个参数期待传入一个引用,但是std::thread得构造函数
    //并不知晓;构造函数无视函数期待的数据类型,并盲目的拷贝已提供的变量。当线程调用func函数
    //时,传递给函数的参数是str拷贝的引用,而非数据本身的引用。使用std::ref可以解决
    //这个问题,将参数转换成引用的形式。
    std::thread workerThread(func,20161016,std::ref(str));
    workerThread.join();

    return 0;
}


(3)使用move

#include <thread>
#include <iostream>
#include <string>

void func(int i,std::string const &s)
{
    std::cout<<"worker thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::cout<<"Hello Word"<<" "<<s<<" "<<i<<std::endl;
}

void func_other(int i,std::string const &s)
{
    std::cout<<"worker thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::cout<<"C++11"<<" "<<s<<" "<<i<<std::endl;
}

int main()
{
    std::cout<<"main thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::string str="at";
    std::thread workerThread1(func,20161016,std::ref(str));
    std::thread workerThread2=std::move(workerThread1);
    workerThread1=std::thread(func_other,20161016,std::ref(str));
    std::thread workerThread3;
    std::thread workerThread4;
    //此句崩溃,workerThread4并未启动
//  workerThread4.join();
    workerThread3=std::move(workerThread2);
    //此句崩溃,因为workerThread1已经关联一个线程
//  workerThread1=std::move(workerThread3);
    workerThread1.join();
    //此句崩溃,因为workerThread2没有关联一个线程
//  workerThread2.join();
    workerThread3.join();

    return 0;
}

2.后台运行线程

#include <thread>
#include <iostream>
#include <string>
#include <chrono>
#include <assert.h>

void func(int i,std::string const &s)
{
    std::cout<<"worker thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::cout<<"Hello Word"<<" "<<s<<" "<<i<<std::endl;
}

int main()
{
    std::cout<<"main thread ID:"<<std::this_thread::get_id()<<std::endl;
    std::string str="at";
    std::thread workerThread(func,20161016,std::ref(str));
    //使用detach()会让线程在后台运行,也就是说主线程不会等待workerThread结束。如果线程detach(),
    //不可能有std::thread对象能引用它,而且不能再调用该线程的join()方法。
    workerThread.detach();
    //workerThread.joinable()为false
    assert(!workerThread.joinable());
    //延时10秒,否则然函数func函数还未执行,main函数就退出了
    std::this_thread::sleep_for(std::chrono::seconds(10));

    return 0;
}

两者区别
在声明一个std::thread对象之后,都可以使用detach和join函数来启动被调线程,区别在于两者是否阻塞主调线程。
1.当使用join()函数时,主调线程阻塞,等待被调线程终止,然后主调线程回收被调线程资源,并继续运行;
2.当使用detach()函数时,主调线程继续运行,被调线程驻留后台运行,主调线程无法再取得该被调线程的控制权。当主调线程结束时,由运行时库负责清理与被调线程相关的资源。

在使用detach时,即使func中有死循环,当进程退出时,该线程也会退出。也就是说,如果进程的main函数返回或者任何线程调用了exit, 整个进程就终止,其中包括它的任何线程。 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草上爬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值