C++ 并发编程指南(2)管理线程

一、创建线程

1、创建线程

线程是通过构造std::thread对象来开始的,该对象指定了线程上要运行的任务,std::thread可以与任何可调用类型一起工作,创建线程的基本语法如下:

#include <thread>
std::thread t(function_name, args...)

创建线程使用的可调用实体如下:

  • 全局函数
  • lambda表达式
  • 函数对象
  • 静态成员函数
  • 非静态成员函数

示例:

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

void Work()
{
    cout << "hello world" << endl;
}

int main()
{
    std::thread myThread(Work);
    myThread.join();  // 阻塞等待线程执行完成

    return 0;
}

2、传递参数给线程

传递参数给可调用对象或函数,基本上就是简单地将额外的参数传递给std::thread构造函数。但重要的是,参数会以值拷贝的方式被复制到内部存储空间,在那里新创建的执行线程可以访问他们。

2.1、传入普通参数

示例:

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

void Display(int a, string str)
{
    cout << "a = " << a << ", str = " << str << endl;
}

int main()
{
    std::thread t(Display, 10, "hello world");
    t.join();

    return 0;
}

2.2、传入引用

示例:

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

struct Point
{
    int x;
    int y;
};

void Modify(Point &p)
{
    p.x = 100;
    p.y = 100;
}

int main()
{
    Point p{66, 66};

    cout << "before modify p.x = " << p.x << "; p.y = " << p.y << endl;

    // 使用 std::ref 传递引用类型给线程函数
    std::thread t(Modify, ref(p));
    t.join();

    cout << "after modify p.x = " << p.x << "; p.y = " << p.y << endl;

    return 0;
}

2.3、传入类的成员函数指针

示例:

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

class MyClass
{
public:
	void Display(int x)
	{
		cout << "x = " << x << endl;
	}
};

int main()
{
    MyClass obj;

    // 类的成员函数做为线程函数入口,需要把对象地址传进去
    std::thread t(MyClass::Display, &obj, 20);
    t.join();

    return 0;
}

二、join与detach

2.1、join

join()函数的作用是让主线程等待该子线程完成,然后主线程再继续执行。这种情况下,子线程可以安全的访问主线程中的资源。子线程结束后由主线程负责回收子线程资源,示例:

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

void Display()
{
    cout << "hello world";
}

int main()
{
    std::thread t(Display);

    // 阻塞等子线程执行完成,再执行主线程操作
    t.join();

    return 0;
}

2.2、detach

detach()称为分离线程函数,使用detach()函数会让线程在后台运行,即主线程不会等待子线程运行结束才结束,通常称分离线程为守护线程(daemon threads)。UNIX中守护线程是指,没有任何显式的用户接口,并在后台运行的线程,这种线程的特点就是长时间运行,示例:

#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;

void Display()
{
    while (true)
    {
        cout << "hello world";
        sleep(1);
    }
}

int main()
{
    std::thread t(Display);

    // 线程分离
    t.detach();

    return 0;
}

2.3、joinable

一个线程对象要么被join(),要么被detach(),如果两者都无,那么线程对象在析构时调用std::terminate使得程序异常结束。一个子线程只能调用join()detach()中的一个,且只允许调用一次。可以调用joinable()来判断是否可以成功调用join()detach()

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值