C++线程之thread详解

C++线程之thread详解

简介

线程是现代程序设计中最重要和有用的概念之一,是使程序在同时执行多个任务的机制。C++语言提供了标准库中的thread类,使得在C++中创建线程非常简单。本文将对thread的用法进行详细的讲解和说明,包括如何创建和管理线程、如何进行线程同步等内容。

创建线程

C++线程库提供了std::thread类用于创建和管理线程。创建线程的最基本方式是提供一个函数,并将其作为参数传递给std::thread构造函数。例如,下面的代码中,我们创建了一个只输出一句话的线程:

#include <iostream>
#include <thread>

void my_thread_function(){
    std::cout << "Hello from my thread!" << std::endl;
}

int main(){
    std::thread my_thread(my_thread_function);
    my_thread.join();
    return 0;
}

在上面的代码中,我们创建了一个名为my_thread_function的函数,并将其作为参数传递给了std::thread类的构造函数。然后,我们通过调用join等待线程执行完毕,然后退出程序。运行上述代码,输出结果为:

Hello from my thread!

可以看到线程已经成功地执行了,输出了我们期望的结果。当std::thread对象被销毁时,它会自动调用join方法等待线程执行完成。

线程同步

多线程应用程序中,同步是一个非常重要的问题。如果没有有效的同步,可能会出现数据竞争、死锁等问题。C++线程库为我们提供了一些同步机制,例如互斥锁和条件变量。

互斥锁

互斥锁是一种同步机制,常用于保护临界区代码,以确保同一时间只有一个线程可以访问该代码块。C++线程库中提供了std::mutex类用于实现互斥锁。

下面的示例代码中,我们通过定义互斥锁来保护global_variable变量的访问。

#include <iostream>
#include <thread>
#include <mutex>

std::mutex my_mutex;
int global_variable = 0;

void my_thread_function(){
    for(int i = 0; i < 10; ++i){
        my_mutex.lock();
        ++global_variable;
        my_mutex.unlock();
    }
}

int main(){
    std::thread my_thread1(my_thread_function);
    std::thread my_thread2(my_thread_function);

    my_thread1.join();
    my_thread2.join();

    std::cout << "global_variable is " << global_variable << std::endl;

    return 0;
}

在上面的代码中,我们创建了两个线程,两个线程都会对global_variable变量进行操作,因此,我们需要对它进行保护。我们使用std::mutex类来定义互斥锁,并在操作之前调用lock方法来获取锁,操作完成后调用unlock方法释放锁。运行上述代码,输出结果为:

global_variable is 20

可以看到,最终global_variable的值为20,证明了两个线程都可以正确地访问并更新该变量。

条件变量

条件变量是一种同步机制,允许线程等待特定条件的满足。C++线程库中提供了std::condition_variable类用于实现条件变量。

下面的示例代码中,我们使用std::condition_variable来实现一个简单的生产者-消费者模型。

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

std::queue<int> my_queue;
std::mutex my_mutex;
std::condition_variable my_cv;

void producer_thread_function(){
    for(int i = 0; i < 10; ++i){
        std::unique_lock<std::mutex> lock(my_mutex);
        my_queue.push(i);
        lock.unlock();
        my_cv.notify_one();
    }
}

void consumer_thread_function(){
    while(true){
        std::unique_lock<std::mutex> lock(my_mutex);
        my_cv.wait(lock, []{ return !my_queue.empty(); });
        int data = my_queue.front();       
        my_queue.pop();
        lock.unlock();
        std::cout << "Consumed: " << data << std::endl;
        if(data == 9) break;
    }
}

int main(){
    std::thread producer_thread(producer_thread_function);
    std::thread consumer_thread(consumer_thread_function);

    producer_thread.join();
    consumer_thread.join();

    return 0;
}

在上面的代码中,我们创建了两个线程,producer_thread_function线程负责生产数据,consumer_thread_function线程负责消费数据。我们使用std::queue保存数据,并与std::mutexstd::condition_variable一起使用,以实现线程的同步和等待。

具体来说,我们在生产者线程中使用unique_lock获取锁,并使用my_cv.notify_one()通知消费者线程有新的数据需要消费。在消费者线程中,我们首先使用my_cv.wait()方法来等待有新的数据可以消费。同时,我们定义了一个lambda表达式作为wait方法的第二个参数,以在等待期间检查队列是否为空。当wait方法返回后,我们使用my_queue.pop()将数据从队列中消费,并使用lock.unlock()释放锁。

运行上述代码,输出结果为:

Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Consumed: 7
Consumed: 8
Consumed: 9

可以看到,数据正确地被生产和消费,证明了我们实现了一个简单的生产者-消费者模型。

结论

以上是对C++线程库中std::thread类的详细介绍和说明。通过本文,我们可以了解到如何使用std::thread类创建和管理线程、如何使用互斥锁和条件变量进行线程同步等内容。希望读者可以通过本文对C++多线程编程有更深入的了解和认识。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++线程之thread详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • java多线程编程之从线程返回数据的两种方法

    首先让我们来了解几个基本的概念: 线程(Thread):计算机中最小的执行单元之一,负责执行程序中指定的任务。 多线程(Multithreading):指在同一个程序中同时执行多个线程,避免单一线程运行太慢造成CPU的浪费。 线程返回数据(Thread Return Data):线程计算完成后,将得到的结果返回给主线程,主线程可以做出相应的操作。 为了实现线…

    多线程 2023年5月16日
    00
  • C++ 数据共享与保护

    C++ 数据共享与保护攻略 1. 数据共享 在C++中,数据共享主要是指多个不同的对象或模块共享同一份数据。要实现数据共享,可以使用全局变量或静态成员变量。 1.1 全局变量 全局变量指声明在函数之外的变量,作用域在整个程序中都可以访问。为了防止数据被其他的文件修改,可以使用static关键字来限制其作用域。 下面是一个使用全局变量实现数据共享的示例: //…

    多线程 2023年5月17日
    00
  • python并发和异步编程实例

    针对“python并发和异步编程实例”的完整攻略,本文将分为以下几个部分进行说明: 并发编程和异步编程的概念解释 并发编程实例演示 异步编程实例演示 总结和建议 1. 并发编程和异步编程的概念解释 在开始讲解并发编程和异步编程实例之前,我们需要先理解这两个概念。 并发编程是指同时执行多个任务,不一定要在同一时刻,但一段时间内它们是交替执行的。 异步编程是指仅…

    多线程 2023年5月16日
    00
  • SpringCloud LoadBalancerClient 负载均衡原理解析

    SpringCloud LoadBalancerClient 负载均衡原理解析 什么是负载均衡? 负载均衡(Load Balancing)是指将工作请求分担到多个计算资源上进行处理,以达到最优化的资源利用、最大化的吞吐量、最小化响应时间、避免单点故障等目的。 传统的负载均衡方式有硬件负载均衡和软件负载均衡,但这些方式都需要使用专门的设备或者软件,且较为昂贵。…

    多线程 2023年5月17日
    00
  • 基于java 线程的几种状态(详解)

    基于 Java 线程的几种状态(详解) 在 Java 语言中,线程是一种非常重要的概念。线程可以被分为多个状态,在不同的状态下,线程的行为和特征是不同的。本文将详细介绍基于 Java 线程的几种状态,并通过两个示例来演示它们。 线程的状态 在 Java 中,线程有以下几种状态: 新建状态(New):线程尚未启动,处于新建状态。 运行状态(Running):线…

    多线程 2023年5月17日
    00
  • python的多线程原来可以这样解

    下面是详细讲解“Python的多线程原来可以这样解”的完整攻略。 什么是多线程? 多线程是指一个进程(程序)中包含多个并发执行的流,每一个流都称为一个线程(Thread),多线程可以将程序中的计算密集型和I/O密集型工作分别交给不同的线程负责,从而提高程序的并发性和效率。 Python中的多线程 Python中的多线程是通过操作系统的线程实现的,Python…

    多线程 2023年5月17日
    00
  • Java多线程基础——Lock类

    Java多线程基础——Lock类 什么是Lock类 Lock类是Java多线程中用来控制并发访问的工具类。与Java的传统的synchronized关键字相比,Lock类具有更强的线程控制能力和更好的性能。 Lock类的使用方法 创建锁对象 在使用Lock对象之前,我们首先需要进行创建。Lock类中有两个最常用的子类:ReentrantLock和Reentr…

    多线程 2023年5月16日
    00
  • Java并发线程池实例分析讲解

    Java并发线程池实例分析讲解 什么是线程池 线程池是一种用于管理多线程的机制,它可以维护一个线程队列,并在这些线程中动态地执行任务。线程池实现了资源的重复利用,在多线程应用中表现出色,可以提高系统的性能。 如何使用线程池 Java提供了一个Executor框架,用于从应用程序中的请求中分离出任务的执行和管理。Java.util.concurrent.Exe…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部