news 2026/10/1 17:35:21

C++创建多线程的方法总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++创建多线程的方法总结

一、多线程预备知识

多线程本质是将程序的运行拆分为部分,每个线程都有自己的执行上下文,包括它的程序计数器,寄存器和栈,并且它们独立地执行,互不干扰。我们必须要明确的是多线程的实现依赖硬件条件:多线程需要多核处理器。多核处理器可以同时执行多个线程,因此多线程可以利用多核处理器的多个内核来实现更快的处理速度和更高的性能。通过使用多核处理器,可以把多个线程并行执行,从而实现更高的性能和更快的处理速度。

比如说,在图像处理应用中,如果使用多核处理器,可以把图像处理任务分成多个独立的部分,并使用多个线程分别执行每个部分。每例如,线程 1 可以处理图像的颜色校正,线程 2 可以处理图像的缩放,线程 3 可以处理图像的旋转等。由于每个线程都可以同时执行,因此处理速度比单线程处理要快得多。需要注意的是,在这种情况下,还需要考虑线程间的同步和通信,以确保线程之间的数据一致性。

二、C++11 std::thread

2.1 创建线程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <iostream>

#include <thread>

voidfoo()

{

std::cout <<"Hello from thread"<< std::endl;

}

intmain()

{

std::threadt1(foo);

t1.join();

return0;

}

在上面的代码中,通过std::thread t1(foo)创建了一个新线程,并在新线程中执行了函数foo。

2.2 线程管理

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <iostream>

#include <thread>

voidfoo()

{

std::cout <<"Hello from thread"<< std::endl;

}

intmain()

{

std::threadt1(foo);

t1.join();

t1.detach();

return0;

}

在上面的代码中,通过调用t1.join()可以等待线程t1结束,并通过调用t1.detach()可以分离线程t1,使线程在后台运行。

std::thread::detach()方法是分离线程的方法,通过调用detach()方法,可以让线程在后台独立运行,不需要等待线程结束即可返回。与调用join()方法不同,分离的线程不受父线程的控制,因此如果父线程结束,分离的线程不会因此结束。请注意,分离的线程一旦开始执行,它将独立运行,不受任何控制,因此不能在父线程中等待它的结束或者通过其他方式获取其结果。如果需要等待线程结束,请使用join()方法。

分离线程的主要作用是让线程在后台独立运行,不需要等待线程结束即可返回。这样可以在不需要等待线程结束的情况下,在父线程中执行其他任务,从而提高程序的效率。

2.3 传递参数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <iostream>

#include <thread>

voidfoo(intx)

{

std::cout <<"Hello from thread, x = "<< x << std::endl;

}

intmain()

{

std::threadt1(foo, 10);

t1.join();

return0;

}

在上面的代码中,通过在创建线程时传递参数10,并在函数foo中读取参数,实现了在线程中传递参数的功能。

2.4 线程间通信

2.4.1 使用共享变量和互斥量(互斥锁):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#include <iostream>

#include <thread>

#include <mutex>

intg_num = 0;

std::mutex g_num_mutex;

voidprint_num() {

while(true) {

g_num_mutex.lock();

if(g_num >= 100) {

g_num_mutex.unlock();

break;

}

std::cout <<"Thread "<< std::this_thread::get_id() <<": "<< g_num++ << std::endl;

g_num_mutex.unlock();

}

}

intmain() {

std::threadt1(print_num);

std::threadt2(print_num);

t1.join();

t2.join();

return0;

}

我们定义了一个全局变量g_num,两个线程分别运行print_num函数。print_num函数不断地对g_num变量进行读写操作,并使用互斥量g_num_mutex对该变量进行加锁。这样可以确保在每次读写操作时,不会有其他线程访问g_num变量。如果g_num的值已经大于等于100,则表示线程退出。最后主线程调用join函数,等待其他线程退出。

2.4.2 使用共享内存

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#include <iostream>

#include <thread>

#include <string>

usingnamespacestd;

string message;

voidwrite_message()

{

message ="Hello World";

}

voidread_message()

{

cout << message << endl;

}

intmain()

{

threadt1(write_message);

threadt2(read_message);

t1.join();

t2.join();

return0;

}

2.5 其他线程相关信息

  • std::thread::hardware_concurrency():返回当前系统支持的最大线程数。
  • std::thread::native_handle():返回线程的原生句柄,在不同的平台中可能不同。
  • std::thread::joinable():判断线程是否可以被 join,如果线程已经结束或者被分离,则返回 false。
  • std::thread::join():等待线程结束,直到线程结束才返回。
  • std::thread::detach():分离线程,使线程可以在后台运行,并且不需要等待其结束。
  • std::thread::get_id():返回线程ID。

三、boost多线程库

官方文档:

Chapter 38. Thread 4.8.0 - 1.73.0

Boost 库中的boost::thread类可以方便地创建和管理多线程。以下是一个使用 Boost 库中的boost::thread类创建多线程的简单示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <iostream>

#include <boost/thread.hpp>

voidworker_thread()

{

std::cout <<"Worker thread is running"<< std::endl;

}

intmain()

{

boost::threadworker(worker_thread);

std::cout <<"Main thread is running"<< std::endl;

worker.join();

return0;

}

四、POSIX线程(Linux&Unix)

C++ POSIX 线程(pthread)库可以帮助您在 C++ 中创建和管理多线程。下面是一个创建和启动一个新线程的示例代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#include <pthread.h>

#include <iostream>

void*thread_func(void*arg)

{

std::cout <<"Thread started with argument: "<< *((int*)arg) << std::endl;

returnNULL;

}

intmain()

{

pthread_t thread_id;

intarg = 42;

// 创建新线程

intresult = pthread_create(&thread_id, NULL, thread_func, &arg);

if(result != 0) {

std::cerr <<"Error: pthread_create() failed"<< std::endl;

return1;

}

// 等待线程结束

result = pthread_join(thread_id, NULL);

if(result != 0) {

std::cerr <<"Error: pthread_join() failed"<< std::endl;

return1;

}

return0;

}

这段代码中,pthread_create函数用于创建一个新线程,并启动它。第一个参数是一个指向线程 ID 的指针,第二个参数指定了线程的属性,通常为NULL,第三个参数是线程函数的地址,最后一个参数是传递给线程函数的参数。

pthread_join函数等待线程结束,第一个参数是线程 ID,第二个参数是接收线程返回值的指针,通常为NULL。

五、 Windows线程库

5.1 线程使用

下面是使用Windows API创建线程并打印数字并获取重要的线程信息的代码示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

#include <iostream>

#include <Windows.h>

DWORDWINAPI ThreadFunction(LPVOIDlpParam)

{

// 获取当前线程ID

DWORDthreadId = GetCurrentThreadId();

std::cout <<"Thread ID: "<< threadId << std::endl;

// 获取线程传入的参数

intthreadParam = *(int*)lpParam;

for(inti = 0; i < threadParam; i++)

{

std::cout << i << std::endl;

}

return0;

}

intmain()

{

intnum = 10;

// 创建线程

HANDLEhThread = CreateThread(NULL, 0, ThreadFunction, &num, 0, NULL);

// 等待线程结束

WaitForSingleObject(hThread, INFINITE);

// 关闭线程句柄

CloseHandle(hThread);

return0;

}

5.2 线程通信

在 Windows API 中,可以使用CreateThread函数创建线程,以下是通过共享变量实现线程间通信的代码示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

#include <Windows.h>

#include <iostream>

DWORDWINAPI ThreadFunction1(LPVOIDlpParam)

{

int* sharedVariable = (int*)lpParam;

while(true)

{

if(*sharedVariable == 0)

{

std::cout <<"Thread 1: sharedVariable = "<< *sharedVariable << std::endl;

*sharedVariable = 1;

}

}

return0;

}

DWORDWINAPI ThreadFunction2(LPVOIDlpParam)

{

int* sharedVariable = (int*)lpParam;

while(true)

{

if(*sharedVariable == 1)

{

std::cout <<"Thread 2: sharedVariable = "<< *sharedVariable << std::endl;

*sharedVariable = 0;

}

}

return0;

}

intmain()

{

intsharedVariable = 0;

HANDLEhThread1 = CreateThread(NULL, 0, ThreadFunction1, &sharedVariable, 0, NULL);

HANDLEhThread2 = CreateThread(NULL, 0, ThreadFunction2, &sharedVariable, 0, NULL);

WaitForMultipleObjects(2, &hThread1, TRUE, INFINITE);

CloseHandle(hThread1);

CloseHandle(hThread2);

return0;

}

在主函数中,我们调用了CreateThread函数创建了两个线程,将共享变量sharedVariable的地址作为参数传入。线程 1 和线程 2 都通过判断共享变量的值来实现通信,它们每当共享变量的值变化时都会输出当前的值。

在这个例子中,WaitForMultipleObjects函数将等待两个线程hThread1和hThread2完成,并且要求等待所有事件对象完成,因此参数bWaitAll的值为TRUE。并且dwMilliseconds的值为INFINITE,所以等待时间是无限的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 17:35:06

HER强化学习实战:用事后经验回放破解稀疏奖励难题

"hindsight"直译过来就是"后见之明"。考试对答案的时候、复盘一场比赛的时候&#xff0c;我们总能清醒地意识到"刚才那步应该那样走"。但在强化学习里&#xff0c;让算法也拥有这种"事后视角"&#xff0c;却是很多机器人控制任务从&qu…

作者头像 李华
网站建设 2026/10/1 17:35:04

微电网能量优化管理实践:从MPC算法到工程落地

1. 微电网能量优化管理&#xff0c;到底在优化什么做微电网项目这些年&#xff0c;被问得最多的一句话是&#xff1a;“你们做的能量优化管理&#xff0c;是不是就是给电池充放电定个时间表&#xff1f;”每次听到我都得摇头。如果只是定个时间表&#xff0c;那叫定时策略&…

作者头像 李华
网站建设 2026/10/1 17:34:52

实战资源:YOLOv3结合OpenCV DNN实现目标检测,附完整代码

简介&#xff1a;这份YOLOv3目标检测资源基于Darknet框架&#xff0c;整合OpenCV图像处理与实时视频分析能力&#xff0c;面向希望快速上手目标检测的开发者&#xff0c;也适合正在搭建智能监控系统、需要进行移动目标识别与跟踪的工程人员&#xff0c;兼顾算法学习与工程落地双…

作者头像 李华
网站建设 2026/10/1 17:33:40

Python随机森林实战:RandomForestClassifier从训练到上线完整指南

简介&#xff1a;这份资源面向刚接触机器学习分类任务的Python学习者与数据挖掘入门者&#xff0c;提供一套可直接运行的随机森林算法示例代码&#xff0c;帮助理解sklearn中RandomForestClassifier的完整调用流程。压缩包共2个文件&#xff0c;包含1个py脚本与1个csv数据文件&…

作者头像 李华
网站建设 2026/10/1 17:33:31

Codex插件精选:10个CLI与IDE高效工具推荐

1. 为什么我最终只留下了这 10 个 Codex 插件Codex 刚火起来那阵子&#xff0c;我跟很多人一样&#xff0c;抱着“先把插件市场翻个底朝天”的心态&#xff0c;一口气装了三十多个插件。结果两周之后&#xff0c;IDE 启动慢得像老牛拉车&#xff0c;命令面板里全是记不住名字的…

作者头像 李华