C++多线程编程——线程的基本概念和使用方法

发布时间 2023-10-29 17:10:28作者: vLiion

什么是线程?

在计算机科学中,线程是进程中的一个执行控制单元,也被称为执行路径。每个进程可以包含多个线程,每条线程并行执行不同的任务。线程是操作系统可识别的最小执行和调度单位。

进程和线程的区别

  1. 进程是程序在某个数据集合上的一次运行活动,也是操作系统进行资源分配和保护的基本单位。每个进程都有独立的地址空间、PCB(进程控制块)和资源。进程可以包含一个或多个线程。
  2. 线程是进程中的一个执行路径,用于保证程序的实时性和实现进程内部的并发。一个进程中至少有一个线程在负责控制程序的执行。如果一个进程有多个执行路径,这个程序就称为多线程程序。

线程发起的例子

让我们通过一个简单的例子来理解线程的概念。假设我们要编写一个C++程序,创建两个线程来同时打印一些消息:

#include <iostream>
#include <thread>

// 线程函数:打印消息
void printMessage(const std::string& message) {
    for (int i = 0; i < 5; ++i) {
        std::cout << message << " (" << i + 1 << ")" << std::endl;
    }
}

int main() {
    // 创建两个线程并启动
    std::thread thread1(printMessage, "Thread 1");
    std::thread thread2(printMessage, "Thread 2");

    // 等待两个线程完成
    thread1.join();
    thread2.join();

    std::cout << "Main thread finished." << std::endl;

    return 0;
}

在上面的例子中,我们创建了两个线程(thread1thread2),每个线程都调用了printMessage函数来打印消息。这两个线程并行执行,输出结果可能交错出现。

detach()函数

当我们在C++中创建线程时,有时我们希望线程在后台运行,不阻塞主线程的执行。这就是detach功能的作用。

detach() 是一个线程对象的成员函数,用于将线程与其创建的执行路径分离。具体来说:

  1. 当我们调用 detach() 时,线程对象不再与主线程关联。这意味着主线程和子线程之间的生命周期不再相互依赖。
  2. 分离后的线程将在后台运行,直到其执行完成或被终止。
  3. 如果主线程结束了,而分离的线程仍在运行,那么分离的线程会继续执行,直到完成。

需要注意以下几点:

  • 分离后的线程不能被加入(join)。
  • 分离后的线程不应该访问主线程中的局部变量或资源,因为它们可能已经被销毁。

lambda表达式作为函数参数传入线程

Lambda表达式是一种匿名函数,可以作为函数参数传递给其他函数。在C++11中,我们可以使用Lambda表达式来代替函数指针。Lambda表达式的语法格式如下:

[capture list] (parameters) -> return type { body }

其中,capture list 用于捕获外部变量,parameters 用于指定参数列表,return type 用于指定返回值类型,body 用于指定函数体。

例如,下面的代码演示了如何将Lambda表达式作为参数传递给线程:

#include <iostream>
#include <thread>

int main() {
    std::thread myThread([](const std::string& str) {
        std::cout << "myThread running ..., str is " << str << std::endl;
    }, "HelloThread");

    myThread.join(); // 分离线程

    // 主线程继续执行其他任务
    std::cout << "Main thread continues." << std::endl;

    // 注意:如果主线程结束了,分离的线程可能还在运行

    return 0;
}

move操作

在C++中,move操作是一种将对象的所有权从一个对象转移到另一个对象的机制,它允许我们避免不必要的拷贝操作,从而提高程序的性能。

在C++11中,标准库提供了一个非常有用的函数 std::move(),它可以将一个左值强制转换为右值引用。具体来说,std::move() 函数将一个左值强制转换为右值引用,并返回一个指向该右值引用的指针。这个指针可以被传递给其他函数,以实现移动语义。