C++多线程编程:其一、thread类概述

thread是C++11版本中出现的线程对象,可以让程序员非常方便地创建线程。

非空的thread对象创建以后,线程就会自动运行起来。简单地理解,一个线程对象中会传入一个函数指针,之后编译器会构造一个栈,将这个函数指针压栈。函数就可以视为任务,从而实现了任务并发。

一、如何创建线程对象:

(1)空thread对象:

cpp 复制代码
thread t;

如果后面没有对其赋值的话,这就是一个毫无意义的操作。

(2)使用全局函数创建thread对象:

cpp 复制代码
void f(){
    cout<<"I love coding"<<endl;
}
int main()
{
    thread t(f);
    t.join();
}

全局函数也可以带参数

cpp 复制代码
void f(int a){
    cout<<"I love coding"<<endl;
    cout<<a;
}
int main()
{
    thread t(f,1);
    t.join();
}

(3)使用静态成员函数创建thread对象:

cpp 复制代码
class A{
public:
    static void f();
};

void A::f(){
    cout<<"I love coding"<<endl;
}
int main()
{
    thread t(A::f);
    t.join();
}

因为静态函数是类公有的,所以只需要标注类名即可。

(4)使用非静态成员函数创建thread对象:

cpp 复制代码
class A{
public:
    void f();
};

void A::f(){
    cout<<"I love coding"<<endl;
}
int main()
{
    A a;
    thread t(&A::f,&a);
    t.join();
}

首先需要将对象构造出来,然后将对象的this指针作为入参。

二、线程持有的资源

网上有各种各样的多线程教程,老生常谈的一句话是"线程持有的资源如何如何"。那么thread到底持有的是什么资源?

本人才疏学浅,操作系统学的实在是不咋地,深入理解不太行。但是这个资源,可以简单看作一个结构体:

cpp 复制代码
_Thrd_t _Thr; //其实_Thrd_t 是类型的别名
 
typedef _Thrd_imp_t _Thrd_t;    // 而_Thrd_imp_t是一个结构体
 
typedef struct {	/* 线程 标识符 */
    void *_Hnd;	    /* 操作系统句柄 */
    unsigned int _Id;    // 线程id
} _Thrd_imp_t;

thread持有的资源,可以看作是一个线程id+一个操作系统句柄。后面会说明,这两个资源,每个thread对象都是不一样的。

所以,thread对象,只能移动构造,不能拷贝构造。只能移动赋值,不能拷贝赋值。

cpp 复制代码
void f(){
}
int main()
{
    thread t1(f);
    cout<<"t1 id : "<<t1.get_id()<<endl<<endl;

    thread t2(move(t1));
    cout<<"t1 id : "<<t1.get_id()<<endl;
    cout<<"t2 id : "<<t2.get_id()<<endl;

    t2.join();
}

输出:

cpp 复制代码
t1 id : 2

t1 id : thread::id of a non-executing thread
t2 id : 2

可见,移动构造之后,t1持有的资源全部给了t2.

假如有一种场景,f()正在执行,发生了资源移动,有问题吗?

没有任何问题。因为线程实际上是操作系统持有的资源,当thread对象创建好以后,线程怎么跑起来和thread对象基本没关系了,thread对象里面不过是保存了一个句柄,句柄就是指向操作系统内核的指针。资源移动无非是将指针转移给了其他的thread对象。

但是,thread保留了这个句柄,说明对象就有了这个线程的所有权,可以阻塞它、分离它,或者进行其他操作。

相关推荐
乌萨奇也要立志学C++9 分钟前
【C++详解】STL-list模拟实现(深度剖析list迭代器,类模板未实例化取嵌套类型问题)
c++·list
闻缺陷则喜何志丹27 分钟前
【前缀和 BFS 并集查找】P3127 [USACO15OPEN] Trapped in the Haybales G|省选-
数据结构·c++·前缀和·宽度优先·洛谷·并集查找
序属秋秋秋2 小时前
《C++初阶之内存管理》【内存分布 + operator new/delete + 定位new】
开发语言·c++·笔记·学习
十秒耿直拆包选手9 小时前
Qt:主窗体(QMainwindow)初始化注意事项
c++·qt
霖0011 小时前
C++学习笔记三
运维·开发语言·c++·笔记·学习·fpga开发
mit6.82411 小时前
[shad-PS4] Vulkan渲染器 | 着色器_重新编译器 | SPIR-V 格式
c++·游戏引擎·ps4
tan77º12 小时前
【Linux网络编程】Socket - TCP
linux·网络·c++·tcp/ip
Mike_Zhang13 小时前
C++使用WinHTTP访问http/https服务
c++
CHANG_THE_WORLD13 小时前
「macOS 系统字体收集器 (C++17 实现)」
开发语言·c++·macos
GiraKoo14 小时前
【GiraKoo】Breakpad 崩溃分析系统
c++