C++ 多线程2025年5月16日 | 阅读 12 分钟 在 C++ 中,多线程是一种强大的技术,它将程序分解为称为线程的小执行单元。多线程允许 CPU 或多核处理器的单个核心同时运行多个线程。使用 C++ 进行编程可以使应用程序将工作分配给能够独立运行或相互通信的自主线程。 ![]() 在现代计算中,利用多个 CPU 核心对于编写响应迅速、高效且可扩展的应用程序至关重要。C++ 多线程使开发人员能够通过代码的并行执行来实现这一点。 什么是线程?在 C++ 中,线程是用于特定进程的某种工作单元。在多道程序环境中,可以并发运行多个进程。同样,我们可以使用线程多次执行同一个进程。在这种情况下,每个进程都与一个称为线程的单元相关联。 创建线程线程类存在于 std::thread 命名空间下。创建该类的实例会启动一个新线程,该线程执行指定的调用任务。 语法 它具有以下语法: 在这个语法中,
C++ 线程示例让我们举一个例子来说明 C++ 中的线程。 示例编译并运行输出 Thread is running. 说明 在此示例中,thread 是用于创建和管理线程的类。之后,join() 方法确保主线程在继续之前等待创建的线程完成。 使用线程的重要头文件要使用 C++ 中的多线程,需要几个头文件。其中一些如下: 定义可调用对象在 C++ 中,可调用对象是指可以由线程执行的任何函数或对象。它包括几个函数,例如函数指针、lambda 表达式以及重载了 operator() 来定义其执行行为的对象。 在 C++ 中,我们可以通过四种方式定义可调用对象。它们如下: 1) 使用函数对象在线程对象中,我们可以使用函数对象作为可调用对象。如果我们想实现该函数对象,我们需要一个类,并在该类中重载 operator()。创建线程时,包含重载函数的代码将被执行。 语法 它具有以下语法: 使用函数对象的 C++ 线程示例让我们举一个例子来说明在 C++ 中使用函数对象的线程。 示例编译并运行输出 Function Object Thread: Value = 10 说明 在此示例中,我们定义了利用 () 运算符重载的 Functor 类。之后,std::thread 的对象构造函数会自动触发在不同线程上执行 operator() 方法。主线程使用 t.join() 方法等待新线程完成。 2) 使用函数指针在 C++ 中,函数指针是为 std::thread 定义可调用对象的最简单、最直接的方法。我们可以将非成员函数的地址传递给线程构造函数。 语法 它具有以下语法: 定义函数后,我们必须使用可调用函数创建线程对象。我们可以将参数传递给对象函数名之后的函数。 使用函数指针的 C++ 线程示例让我们举一个例子来说明在 C++ 中使用函数指针的线程。 示例编译并运行输出 Function Pointer Thread: Value = 20 3) 使用 Lambda 表达式在 C++ 中,lambda 表达式可以直接用作可调用对象来创建 std::thread。Lambda 主要用于快速的、内联的任务,而无需定义单独的函数。 语法 它具有以下语法: 在上面的例子中,主函数必须等待直到线程 t1 完成。通常,线程的 join 函数会阻止其他操作/功能,直到调用线程完成其执行。 使用 Lambda 表达式的 C++ 线程示例让我们举一个例子来说明在 C++ 中使用 lambda 表达式的线程。 示例编译并运行输出 Lambda Thread: Value = 30 说明 在此示例中,我们使用 lambda 创建匿名函数,这些函数直接存在于代码中。std::thread 构造函数需要 lambda 函数及其参数。 4) 使用成员函数在 C++ 中,我们可以将类成员函数用作 std::thread 的可调用对象。它允许我们创建操作特定对象的线程。 语法 它具有以下语法: 使用成员函数的 C++ 线程示例让我们举一个例子来说明在 C++ 中使用成员函数的线程。 示例编译并运行输出 Car is Running: 1 Car is Running: 2 Car is Running: 3 Car is Running: 4 Car is Running: 5 说明 在此示例中,我们取了成员函数 run() 的 &Car::run 指针。之后,&car 是调用成员函数的对象。6 是传递给 run 函数的参数。最后,t.join() 函数确保主线程等待子线程完成。 可调用线程示例我们在下面的程序中提供了一个完整的代码示例,用于创建和执行线程。 示例编译并运行输出 Thread 1 :: callable => function pointer Thread 3 :: callable => lambda expression Thread 3 :: callable => lambda expression Thread 2 :: callable => function object Thread 2 :: callable => function object Thread 1 :: callable => function pointer 说明 在此示例中,我们使用三种不同的可调用对象(函数指针、对象和 lambda 表达式)创建了三个线程。我们创建了每个线程的两个实例并启动它们。如输出所示,三个线程同时独立地运行。 C++ 中的线程管理在 C++ 中,线程管理涉及控制和协调由 std::thread 类创建过程产生的线程。线程管理需要有效的执行监督,以及适当的同步方法和终止程序,以及正确清理资源以防止数据竞争、内存泄漏和未定义行为。 定义了几个函数来管理线程。它们可以重用于执行多项任务。
C++ 线程管理示例让我们举一个例子来说明 C++ 中线程的几个函数。 示例编译并运行输出 System supports 4 concurrent threads. Thread 2 started. ID: 131265380484800 Thread 3 started. ID: 131265369999040 Thread 1 started. ID: 131265390970560 Thread IDs: t1: 131265390970560 t2: 131265380484800 t3: 131265369999040 t4: 131265359513280 Thread 4 started. ID: 131265359513280 Thread 3 finished. Thread 4 finished. Thread Thread 2 finished. 1 finished. Main thread ends after managing all threads. 说明 在此示例中,我们通过使用 std::thread 功能来演示 C++ 线程管理。该程序创建了四个线程,同时 join 了另外三个线程,并允许一个线程独立运行。输出显示了线程标识符以及用于并发操作的操作系统详细信息。 多线程的优势C++ 多线程的几个好处如下:
多线程中的上下文切换CPU 执行在不同线程之间执行上下文切换。操作系统需要创建当前线程状态的备份并检索下一个线程的状态,以实现多个线程的运行。多任务操作所需的上下文切换会产生性能开销,当上下文频繁更改时,会特别影响执行速度。 C++ 多线程上下文切换示例让我们举一个例子来说明 C++ 中多线程的上下文切换。 示例编译并运行输出 Total time taken: 0.0120467 seconds 说明 在此示例中,我们找到了使用线程并发运行的两个任务的执行时间。之后,它使用 std::chrono 记录开始和结束时间,创建两个线程来同时执行 task1 和 task2,然后 join 它们,最后计算并打印总耗时。 在 C++ 中向线程传递参数在 C++ 线程中,我们可以使用 std::thread 构造函数中的结构来传递多个参数。它允许我们将参数复制或移动到线程对象的内部存储中,然后将其传递给可调用对象。 语法 它具有以下语法: C++ 向线程传递参数示例让我们举一个例子来说明在 C++ 中向线程传递参数。 示例编译并运行输出 Hello! this is from thread 0 Hello! this is from thread 1 Hello! this is from thread 2 说明 在此示例中,我们创建了一个单独的线程来执行 show_message 函数,该函数会显示三次消息。之后,t.join() 调用确保主线程在退出前等待创建的线程完成执行。 多线程问题C++ 中多线程的几个问题如下: 1) 竞争条件 在 C++ 中,当多个线程并发访问公共数据,并且它们的运行操作顺序取决于它们运行时的时间点时,就会发生竞争条件。如果没有适当的同步,这可能导致数据损坏和不一致的结果。 2) 死锁 在 C++ 中,当多个线程卡在某个状态,它们需要其他线程的资源,同时又相互阻塞时,就会发生死锁,导致它们都无法继续。死锁在应用程序执行过程中发生,因为线程获取的资源锁形成了循环模式。 3) 活锁 在 C++ 中,活锁发生在死锁之间,因为活跃的线程在尝试打破资源冲突时会卡在无限循环中。 4) 饥饿 线程饥饿发生是因为线程需要资源很长时间,但其他线程却一直在占用这些资源。基于优先级的调度方法可能会导致低优先级线程永久被阻塞的死锁。 C++ 多线程选择题1) 在 C++ 中,如果 std::thread 被创建但未在销毁前 join 或 detach,会发生什么?
答案:c) 程序执行将产生一个异常,从而终止正在运行的代码。 2) 以下关于 C++ 中 std::async 函数的陈述,哪项是准确的?
答案:b) 它会延迟执行直到调用 get()。 3) C++ 多线程中 std::mutex 的主要目的是什么?
答案:c) 锁定共享资源以实现线程安全 4) 以下哪个选项是使用 C++ 中已分离线程的主要缺点?
答案:b) 父线程无法访问其结果。 5) 在 C++ 中使用 std::thread 创建线程的以下哪种方式是无效的?
答案:d) 调用线程对象的 run() 下一主题C++ 中的静态对象 |
简介 Abdul Bari 在计算机科学教育领域以其在传授编程语言和算法知识方面的熟练程度而闻名。Bari 凭借其揭开复杂概念神秘面纱的热情,对无数学生和有抱负的程序员的生活产生了深远的影响。在...
阅读 4 分钟
这个百货商店管理系统完全基于提供有关添加、计算和检查产品以及其他功能的信息。管理员或客户可以毫无压力地了解数据。该系统能够减少付款...
阅读 6 分钟
在本文中,我们将通过示例进行讨论。拔河是最著名的计算机科学和数学问题之一。它通常被称为平衡问题。在此任务中,我们采用一组权重,我们的目标是...
阅读 6 分钟
当 C++ 编译器遇到它不理解的语句或表达式,或者它没有按照语言规则正确编写时,它通常会产生“Expected unqualified id”错误。“expected unqualified id”错误在 C++ 中通常表示编译器遇到了一个情况...
阅读 4 分钟
override 关键字对于确保代码的正确性和可维护性至关重要,尤其是在面向对象编程和多态性中。它是 C++11(及更高版本)的一个特性,允许您明确表示派生类成员函数旨在覆盖虚拟...
5 分钟阅读
在本文中,我们将讨论 C/C++ 中的 strxfrm() 函数及其语法和示例。strxfrm() 函数是什么?strxfrm() 函数是 C/C++ 库中的一个函数。它用于在转换源字符串中的字符后将其插入目标字符串...
阅读 2 分钟
在 C++ 中添加两个数字是一项基本操作,并且是许多更复杂的算术运算的基础。它在许多方面都很重要。首先,两个数字相加是一项基本的数学运算,在日常生活中被用作……
阅读 3 分钟
unordered_multimap rehash(N) 函数在 C++ 中将容器中的元素数量增加到 n 或更多。如果 n 大于容器中的元素数量,则需要重新哈希。新元素计数可能等于或大于...
阅读 3 分钟
Calloc 用于动态地为变量或数组分配内存。它将内存初始化为零。它在 C 语言中很受欢迎,但在 C++ 中也可以使用。在 C++ 语言中,我们使用 new 函数 new[] 等关键字进行内存分配...
阅读 4 分钟
C++ 中的自底向上方法是一种软件开发策略,它涉及将复杂的系统分解为更小、更易于管理的部分,然后将这些部分构建成一个更大、更全面的程序。这种方法可以与自顶向下方法相对应,后者从...
阅读 3 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India