C++多线程

本文详细介绍了C++中的多线程概念,包括线程的状态、进程与线程的关系,以及多线程的原因。文章重点讲解了如何创建线程、线程同步的多种方法,如互斥对象、事件对象、信号量和关键代码段,并提供了相应的API示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程的基本概念

基本概念:线程,即轻量级进程(LWP:LightWeight Process),是程序执行流的最小单元。一个标准的线程由线程ID、当前指令指针(PC),寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程不拥有系统资源,近拥有少量运行必须的资源。

线程的基本状态

基本状态:就绪、阻塞和运行三种基本状态。

就绪状态:指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;

运行状态:指线程占有处理机正在运行;

阻塞状态:指线程在等待一个事件(如信号量),逻辑上不可执行。

进程和线程的关系

简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

为什么使用多线程

  1. 避免阻塞 大家知道,单个进程只有一个主线程,当主线程阻塞的时候,整个进程也就阻塞 了,无法再去做其它的一些功能了。
  2. 避免 CPU 空转 应用程序经常会涉及到 RPC,数据库访问,磁盘 IO 等操作,这些操作的速度比 CPU 慢很多,而在等待这些响应时,CPU 却不能去处理新的请求,导致这种单线 程的应用程序性能很差。 cpu > 内存 > 磁盘
  3. 提升效率 一个进程要独立拥有 4GB 的虚拟地址空间,而多个线程可以共享同一地址空间, 线程的切换比进程的切换要快得多。

创建线程

CreateThread
需要添加<windows.h>

HANDLE CreateThread(
 LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD 
 SIZE_T dwStackSize,//initialstacksize 
 LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction
 LPVOID lpParameter,//threadargument 
 DWORD dwCreationFlags,//creationoption
 LPDWORD lpThreadId//threadidentifier 
 )

1.第一个参数 lpThreadAttributes 表示线程内核对象的安全属性,一般传入 NULL 表示使用默认设置。

2.第二个参数 dwStackSize 表示线程栈空间大小。传入 0 表示使用默认大小 (1MB)。

3.第三个参数 lpStartAddress 表示新线程所执行的线程函数地址,多个线程 可以使用同一个函数地址。

4.第四个参数 lpParameter 是传给线程函数的参数。

5.第五个参数 dwCreationFlags 指定额外的标志来控制线程的创建,为 0 表 示线程创建之后立即就可以进行调度,如果为 CREATE_SUSPENDED 则表 示线程创建后暂停运行,这样它就无法调度,直到调用 ResumeThread()。

6.第六个参数 lpThreadId 将返回线程的 ID 号,传入 NULL 表示不需要返回 该线程 ID 号

例子:

#include <iostream>
#include <windows.h>

DWORD WINAPI LaoWang(void* arg)
{
   
	int count = *(int*)arg;
	for (int i = 0; i < count; i++)
	{
   
		Sleep(4000);
		puts("老王唱歌");
	}
	return 0;
}

DWORD WINAPI XiaoHong(void* arg)
{
   
	int count = *(int*)arg;
	for (int i = 0; i < count; i++)
	{
   
		Sleep(3000);
		puts("小红俯卧撑");
	}
	return 0;
}

DWORD WINAPI XiaoMing(void* arg)
{
   
	int count = *(int*)arg;
	for (int i = 0; i < count; i++)
	{
   
		Sleep(2000);
		puts("小明甩头发");
	}
	return 0;
}

int main() 
{
   
	HANDLE threadArry[3];
	int laowang = 30, xiaohong = 30, xiaoming = 30;
	threadArry[0] = CreateThread(NULL, 0, LaoWang, (void*)&laowang, 0, NULL);
	threadArry[1] = CreateThread(NULL, 0, XiaoHong, (void*)&xiaohong, 0, NULL);
	threadArry[2] = CreateThread(NULL, 0, XiaoMing, (void*)&xiaoming, 0, NULL);
	WaitForMultipleObjects(3,threadArry,TRUE, INFINITE);
	for (int i = 0; i < 3; i++)
	{
   
		CloseHandle(threadArry[i]);
	}
}

_beginthreadex
需要添加<process.h>库
需要添加<<windows.h>库

unsigned long _beginthreadex( 
void *security, // 安全属性, 为 NULL 时表示默认安全性 
unsigned stack_size, // 线程的堆栈大小, 一般默认为 0 
unsigned(_stdcall *start_address)(void *), // 线程函数 
void *argilist, // 线程函数的参数 
unsigned initflag, // 新线程的初始状态,0 表示立即执行,//CREATE_SUSPENDED 表示创建之后挂起 
unsigned *threaddr // 用来接收线程 ID 
);
//返回值 : // 成功返回新线程句柄, 失败返回 0
// __stdcall 表示 1.参数从右向左压入堆栈 2.函数被调用者修改堆栈

例子:

#include <iostream>
<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值