当前位置:网站首页 > 技术博客 > 正文

c++多线程调用python



线程是程序中的轻量级执行单元,允许程序同时执行多个任务。

多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。

一般情况下,两种类型的多任务处理:基于进程和基于线程

  • 基于进程的多任务处理是程序的并发执行。
  • 基于线程的多任务处理是同一程序的片段的并发执行。

C++ 多线程编程涉及在一个程序中创建和管理多个并发执行的线程。

C++ 提供了强大的多线程支持,特别是在 C++11 标准及其之后,通过 标准库使得多线程编程变得更加简单和安全。


  • 线程是程序执行中的单一顺序控制流,多个线程可以在同一个进程中独立运行。
  • 线程共享进程的地址空间、文件描述符、堆和全局变量等资源,但每个线程有自己的栈、寄存器和程序计数器。

  • 并发:多个任务在时间片段内交替执行,表现出同时进行的效果。
  • 并行:多个任务在多个处理器或处理器核上同时执行。

C++11 及以后的标准提供了多线程支持,核心组件包括:

  • :用于创建和管理线程。
  • :用于线程之间的互斥,防止多个线程同时访问共享资源。
  • :用于管理锁的获取和释放。
  • :用于线程间的条件变量,协调线程间的等待和通知。
  • :用于实现线程间的值传递和任务同步。

C++ 11 之后添加了新的标准线程库 , 在 <thread> 头文件中声明,因此使用 时需要包含 在 <thread> 头文件。

注意:之前一些编译器使用 C++ 11 的编译参数是 -std=c++11:

g++ -std=c++11 test.cpp 

std::thread

#include<thread> std::thread thread_object(callable, args...);

  • :可调用对象,可以是函数指针、函数对象、Lambda 表达式等。
  • :传递给 的参数列表。

通过函数指针创建线程,这是最基本的方式:

使用 编译后,执行输出结果为:

Hello from thread (function pointer)! Hello from thread (function pointer)! Hello from thread (function pointer)! Hello from thread (function pointer)! Hello from thread (function pointer)!

通过类中的 方法定义函数对象来创建线程:

使用 编译后,执行输出结果为:

Hello from thread (function object)! Hello from thread (function object)! Hello from thread (function object)! Hello from thread (function object)! Hello from thread (function object)!

Lambda 表达式可以直接内联定义线程执行的代码:

使用 编译后,执行输出结果为:

Hello from thread (lambda)! Hello from thread (lambda)! Hello from thread (lambda)! Hello from thread (lambda)! Hello from thread (lambda)!


join() 用于等待线程完成执行。如果不调用 join() 或 detach() 而直接销毁线程对象,会导致程序崩溃。

 t.join();

detach() 将线程与主线程分离,线程在后台独立运行,主线程不再等待它。

 t.detach();

参数可以通过值传递给线程:

 std::thread t(func, arg1, arg2);

如果需要传递引用参数,需要使用 std::ref:


以下是一个完整的示例,展示了如何使用上述三种方式创建线程,并进行线程管理。

使用 C++ 11 的编译参数 -std=c++11:

g++ -std=c++11 test.cpp 

当上面的代码被编译和执行时,它会产生下列结果:

线程 1 、2 、3 独立运行 线程使用函数指针作为可调用参数 线程使用函数指针作为可调用参数 线程使用函数指针作为可调用参数 线程使用函数对象作为可调用参数 线程使用函数对象作为可调用参数 线程使用函数对象作为可调用参数 线程使用 lambda 表达式作为可调用参数 线程使用 lambda 表达式作为可调用参数 线程使用 lambda 表达式作为可调用参数


在多线程编程中,线程同步与互斥是两个非常重要的概念,它们用于控制多个线程对共享资源的访问,以避免数据竞争、死锁等问题。

互斥量是一种同步原语,用于防止多个线程同时访问共享资源。当一个线程需要访问共享资源时,它首先需要锁定(lock)互斥量。如果互斥量已经被其他线程锁定,那么请求锁定的线程将被阻塞,直到互斥量被解锁(unlock)。

:用于保护共享资源,防止数据竞争。

std::mutex mtx; mtx.lock(); // 锁定互斥锁 // 访问共享资源 mtx.unlock(); // 释放互斥锁

和 :自动管理锁的获取和释放。

std::lock_guard<std::mutex> lock(mtx); // 自动锁定和解锁 // 访问共享资源

互斥量的使用示例:

C++提供了多种锁类型,用于简化互斥量的使用和管理。

常见的锁类型包括:

  • std::lock_guard:作用域锁,当构造时自动锁定互斥量,当析构时自动解锁。
  • std::unique_lock:与std::lock_guard类似,但提供了更多的灵活性,例如可以转移所有权和手动解锁。

锁的使用示例:

条件变量用于线程间的协调,允许一个或多个线程等待某个条件的发生。它通常与互斥量一起使用,以实现线程间的同步。

用于实现线程间的等待和通知机制。

std::condition_variable cv; std::mutex mtx; bool ready = false; std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return ready; }); // 等待条件满足 // 条件满足后执行

条件变量的使用示例:

原子操作确保对共享数据的访问是不可分割的,即在多线程环境下,原子操作要么完全执行,要么完全不执行,不会出现中间状态。

原子操作的使用示例:

线程局部存储允许每个线程拥有自己的数据副本。这可以通过thread_local关键字实现,避免了对共享资源的争用。

线程局部存储的使用示例:

死锁发生在多个线程互相等待对方释放资源,但没有一个线程能够继续执行。避免死锁的策略包括:

  • 总是以相同的顺序请求资源。
  • 使用超时来尝试获取资源。
  • 使用死锁检测算法。


std::future 和 std::promise:实现线程间的值传递。

消息队列(基于 std::queue 和 std::mutex)实现简单的线程间通信。


C++17 引入了并行算法库(),其中部分算法支持并行执行,可以利用多核 CPU 提高性能。

更多实例参考:

C++ 多线程: http://www.runoob.com/w3cnote/cpp-multithread-demo.html

C++ std::thread: https://www.runoob.com/w3cnote/cpp-std-thread.html

版权声明


相关文章:

  • 如何设计一个高并发高可用系统2025-04-30 14:30:04
  • 什么叫指针数组2025-04-30 14:30:04
  • 运维监控系统有哪些2025-04-30 14:30:04
  • jsoncpp rapidjson2025-04-30 14:30:04
  • contain_of宏2025-04-30 14:30:04
  • linux系统文件权限有几种2025-04-30 14:30:04
  • redis教程(Linux下安装redis并配置开机自启保姆级教程-----附带每一步截图)2025-04-30 14:30:04
  • 怎么知道小程序的appid2025-04-30 14:30:04
  • geohash转换为经纬度2025-04-30 14:30:04
  • 树莓派3b和3b+系统通用2025-04-30 14:30:04