首页 > 编程语言 >C++多线程编程——线程的基本概念和使用方法

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

时间:2023-10-29 17:11:32浏览次数:37  
标签:std 执行 函数 C++ 线程 进程 多线程

什么是线程?

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

进程和线程的区别

  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() 函数将一个左值强制转换为右值引用,并返回一个指向该右值引用的指针。这个指针可以被传递给其他函数,以实现移动语义。

标签:std,执行,函数,C++,线程,进程,多线程
From: https://www.cnblogs.com/vLiion/p/17796059.html

相关文章

  • 【C++】继承 ⑬ ( 虚继承原理 | 虚继承解决继承二义性问题 | 二义性产生的原因分析 )
    文章目录一、虚继承原理1、虚继承解决继承二义性问题2、二义性产生的原因分析3、虚继承原理二、代码示例-虚继承原理1、完整代码示例2、执行结果一、虚继承原理1、虚继承解决继承二义性问题继承的二义性:如果一个子类(派生类)继承多个父类(基类),这些父类都继......
  • 【C++】继承 ⑩ ( 继承机制中的 static 静态成员 | 子类中访问父类静态成员的方法 )
    文章目录一、继承机制中派生类中的static关键字1、子类继承父类静态成员2、父类静态成员访问控制权限的改变3、子类如何访问父类静态成员4、静态成员使用要点二、完整代码示例一、继承机制中派生类中的static关键字1、子类继承父类静态成员子类继承父类静态成员:父类(......
  • java实现多线程下载器
    前言:......
  • 【C++】继承 ⑫ ( 继承的二义性 | virtual 虚继承 )
    文章目录一、继承的二义性1、场景说明-继承的二义性2、继承中的二义性报错3、完整代码示例二、virtual虚继承1、虚继承引入2、虚继承语法3、代码示例-虚继承一、继承的二义性1、场景说明-继承的二义性A类是父类,B类和C类继承A类,是子类,D类多继承B类......
  • 四种常见线程池的原理
    newFixedThreadPool(固定数目线程的线程池)newCachedThreadPool(可缓存线程的线程池)newSingleThreadExecutor(单线程的线程池)newScheduledThreadPool(定时及周期执行的线程池)前三种线程池的构造直接调用ThreadPoolExecutor的构造方法。newSingleThreadExecutorpublicsta......
  • 万字长文 | 业内 MySQL 线程池主流方案详解 - MariaDB/Percona/AliSQL/TXSQL/MySQL企
    作者:卢文双资深数据库内核研发本文首发于2023-05-0422:07:40http://dbkernel.com/2023/05/04/mysql-threadpool-main-solutions-details/#本文主要从功能层面对比percona-server、mariadb、阿里云AliSQL、腾讯TXSQL、MySQL企业版线程池方案,都基于MySQL8.0。至于源......
  • c++中重载、重写、隐藏的区别
    重载:同一个函数的不同表现形式。同一个类中;函数原型不同(函数名相同,参数列表即顺序、个数、类型不同);virtual关键字可有可无。 重写:继承关系中,派生类对基类同名函数有不同的表现形式。有继承关系的类;函数原型相同;基类成员函数必须声明为虚函数(virtual)。 隐藏:继......
  • C++ | 每一个C++程序员都应该知道的RAII
    导读:RAII是C++中一种管理资源、避免资源泄漏的惯用法,利用栈的特点来实现。本文较为详细介绍了RAII的原理、使用方法和优点,并且通过实例讲解了RAII在C++STL中的应用,如智能指针和互斥锁等,在最后进行了编程实践。本文适合对C++编程有一定了解的开发者阅读。1.什么是RAIIRAII是R......
  • C和C++的区别
    1.头文件(c++标准头文件都是有命名空间的);2.c++有命名空间,可以解决命名冲突的问题;3.输入与输出1)c++:读入std::cin<<     输出std::cout>>std::endl;2)c:读入:scanf输出:printf4.对空间的开辟和释放c:malloc,calloc,realloc,free......
  • C++---数据结构---队列(queue)
    queue容器queue基本概念概念:Queue是一种先进先出(FirstInFirstOut,FIFO)的数据结构,它有两个出口队列容器允许从一端新增元素,从另一端移除元素队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为队列中进数据称为—入队push队列中出数据称为—出队popque......