C++11多线程基础一

本文介绍了并发的基本概念,包括并发、进程和线程,并详细阐述了C++11中如何通过全局函数、函数对象、类成员函数以及lambda表达式创建线程。同时,讨论了`detach()`和`joinable()`成员函数在多线程管理中的作用,强调了进程间通信与线程同步的重要性。
摘要由CSDN通过智能技术生成

一、基本概念(通俗理解)

1.1并发

一个程序同时执行多个独立的任务,就是一种并发。采用并发技术的目的是同时进行多个任务,提高性能。

1.2进程

首先介绍一下可执行程序,在windows系统下,如后缀名为.exe的文件(如图1中的第一个文件)。

图1 windos下的文件 图 1Windows下文件

在linux系统下,如gcc -o 命令生成的文件(如图2种绿色的文件)
图2 linux某目录下的文件图2 linux某目录下的文件

一个可执行程序运行起来,就叫创建了一个进程。在Windows下可以在任务管理器中查看正在运行的进程
在这里插入图片描述图3 Windows下的进程

注意,计算机的CPU是多核的,但并不是所有的进程都是同时进行的,因为进程的数量远远高于cpu的核数,cpu的每个核就可以执行多个进程,但这些进程是在时间上穿插完。

1.3线程

每个进程都有一个主线程,这个主线程是唯一的。主线程随着进程默认启动,与进程唇齿相依,有进程就有主线程,主线程结束,进程也就结束。运行程序时,实际上是进程的主线程来执行main函数中的代码,线程可以理解为一条代码的执行通路,每创建一个新线程,就可以在同一时刻,多干一个不同的事情。线程并不是越多越好,每个线程,都需要一个独立的堆栈空间(1M左右),线程中的切换要保存很多中间状态。

二、并发的实现方法

实现并发的手段:(1) 通过多个进程;(2) 在单独一个进程中创建多个线程。

2.1多进程并发

进程之间的通讯:同一个电脑上,管道,文件,消息队列,共享内存;不同电脑上:socket通信技术。

2.2多线程并发

每个线程都已自己独立的运行路线,但是一个进程中的不同线程共享地址空间(一个线程中定义的变量可以在另一个线程中调用)
使用多线程并发的开销远远小于多进程并发的开销。
共享内存带来数据一致性问题:多个线程在同一时刻往所共享的内存空间写入数据,会出现覆盖问题。
多进程和多线程虽然可以混合使用,但优先考虑多线程手段。

2.3c++11中创建线程

2.3.1通过全局函数

c++11通过thread类模板创建线程,
第一步,使用时要帮头文件

#include<thread>

第二步,创建初始函数:下图中的thread函数。

int mythread()
{
	std::cout << "子线程开始执行,线程ID为" << std::this_thread::get_id() << std::endl;
	std::chrono::microseconds dur(7000);
	std::this_thread::sleep_for(dur);
	std::cout << "子线程结束执行,线程ID为" << std::this_thread::get_id() << std::endl;
	return 15;
}

第三步,main中写代码:定义thread类的对象。

thread myobj(my_print);  //创建了一个线程对象,是子线程执行起点。
​myobj.join();     //阻塞主线程,让主线程等待子线程执行完毕,然后主线程和子线程汇合,主线程再继续。

2.3.2通过函数对象(仿函数)

class TA
{void operator()(){//......}
}

主函数中程序

TA a;
thread myobj(a);
myobj.join();

2.3.3通过类成员函数

class A
{
public:
	void Receive()
	{
		for (int i = 0; i < 100000; i++)
		{
			cout << "接收数据的线程开始工作了:正在接收第" << i << "个数据\n";
			ReMessages.push_back(i);
		}
	}
	void Send()
	{

		for (int i = 0; i < 100000; i++)
		{
			if(!ReMessages.empty())
			{
				cout << "发送数据的线程开始工作了:正在发送第" << i << "个数据\n";
				int command = ReMessages.front();
				ReMessages.pop_front();
			}
			else
			{
				cout << "数据为空" << endl;
			}
		}
	}
private:
	list<int> ReMessages;
};

主函数中程序

A a;
	std::thread myobj(&A::Receive, &a);
	std::thread myobj1(&A::Send, &a);
	myobj1.join();
	myobj.join();

2.3.4使用lambda表达式

auto mylambda=[]
{
//.....
}
thread myobj(mylambda);
myobj.join();

2.2thread中的detach()成员函数

创建玩thread类对象后,如果调用的不是join()成员函数,而是detach()成员函数,这样的话主线程不会等子线程,但主线程的结束不影响子线程的执行。
为什么引入detach,因为如果创建了很多子线程,让主线程等待子线程结束,这种编程方法不太好。
一旦一个线程detach后,该线程就会和主线程分离,此时子线程会驻留在后台运行,即被c++运行时库接管,而不被我们控制,当这个子线程执行完成后,由运行时库负责清理线程相关的资源(linux里面的守护线程)。
主线程结束后,子线程如果没有执行完会继续执行,但不会在往终端上输出东西了。
join和detach成员函数,thread对象只能调用其中的一个。

2.3 joinable()成员函数

判断是否可以成功使用join或者detach。
返回值为 true或者false。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值