【C++11】线程库

目录

一、thread类的简单介绍

二、thread类的使用

2.1 关键成员函数及其功能

2.2 并发和并行

2.3 线程函数参数

2.4 原子性操作库(atomic)

三、mutex的使用

3.1 互斥量的种类

3.2 lock_guard

3.3 unique_lock


一、thread类的简单介绍

在C++11中,实际上既可以说存在“线程类”,也可以说引入了“线程库”的支持。更准确地说,C++11标准库通过<thread>头文件提供了一系列与线程相关的类和函数,这些共同构成了C++11的线程库。

C++11中的线程类

C++11标准库通过<thread>头文件提供了一系列与线程相关的类和函数,这些共同构成了C++11的线程库。C++11对线程进行支持,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的线程,必须包含< thread >头文件。

二、thread类的使用

2.1 关键成员函数及其功能

构造函数

thread()    构造一个线程对象,没有关联任何线程函数,不启动任何线程。
thread(fn,args1, args2,...)    构造一个线程对象,并启动一个新线程来执行函数fn,(args1,args2,...)为线程函数的参数。线程函数可以是可执行对象(函数指针、仿函数、lambda、包装器)。

注:

  1. 不支持拷贝构造以及赋值,但支持移动构造和移动赋值。
  2. 带参构造,创建可执行线程。
  3. 先创建空线程对象,移动构造或者移动赋值,把右值线程对象转移过去。

线程id

thread::id  线程id,唯一标识一个线程。

id get_id() const noexcept;    返回当前线程的 thread::id 对象,用来唯一标识一个线程。noexcept 关键字用于指定函数不会抛出异常。

thread::id this_thread::get_id() noexcept;      线程对象调用的函数获取当前执行线程的 ID

阻塞当前线程

void jion();     该函数调用后会阻塞住线程,当该线程结束后,主线程继续执行.

bool joinable() const noexcept;     检查thread对象是否代表一个可连接的线程,如果线程已经启动且尚未被 join() 或 detach() 调用,则该函数返回 true。如果线程是空的或已经被 join() 或 detach() 调用,则返回 false。

线程分离 

void detach();     在创建线程对象后马上调用,把被创建线程与线程对象分离开,分离的线程变为后台线程,创建的线程的"死活"就与主线程无关。

注意:

  1. 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的
    状态。
  2. 当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。
  3. thread类是防拷贝的,不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即将一个
    线程对象关联线程的状态转移给其他线程对象,转移期间不影响线程的执行。
  4. 在线程对象销毁之前,必须要么调用 join() 要么调用 detach(),否则程序将终止线程并引发异常。
  5. 一旦线程被分离(detach),就不能再被连接(join),且线程对象不再与任何线程关联。
  6. 调用 join() 或 detach() 后,std::thread 对象不再表示任何线程,因此这些操作只能对每个线程对象执行一次。
  7. 可以通过jionable()函数判断线程是否是有效的,如果是以下任意情况,则线程无效
    采用无参构造函数构造的线程对象;
    线程对象的状态已经转移给其他线程对象;
    线程已经调用jion或者detach结束;

 简单举例:

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

void PrintThreadId()
{
	thread::id id = this_thread::get_id();//线程对象调用的函数获取当前执行线程的 ID要使用this_thread::get_id(),而不是get_id()
	cout << "Thread ID: " << id << endl;
}

void Func1()
{
	//创建线程
	thread t1(PrintThreadId);

	//获取线程id
	thread::id t1_id = t1.get_id();
	cout << "Thread 1 ID: " << t1_id << endl;

	// 判断线程是否可连接
	if (t1.joinable())
		t1.join();
	else
		cout << "Thread 1 is not joinable." << endl;

	//创建另一个线程
	thread t2(PrintThreadId);

	//获取线程id
	thread::id t2_id = t2.get_id();
	cout << "Thread 2 ID: " << t2_id << endl;

	// 判断线程是否可连接
	if (t2.joinable())
		t2.join();
	else
		cout << "Thread 2 is not joinable." << endl;

	return;
}

int main()
{
	Func1();
	return 0;
}

有时输出结果可能混乱,这是由于线程间竞争条件和同步问题造成的,如多线程同时尝试写入同一个输出流。

2.2 并发和并行

并发(Concurrency)与并行(Parallelism)是两个经常被混淆的概念,但在计算机科学中它们有明确的定义和区别。

并发
并发指的是两个或多个事件在同一时间段内发生。在多线程或多进程编程中ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值