首页 > 编程语言 >C++多线程编程:利用线程提高程序并发性

C++多线程编程:利用线程提高程序并发性

时间:2023-12-02 13:32:44浏览次数:41  
标签:std int 编程 C++ 线程 多线程

C++多线程编程:利用线程提高程序并发性

引言

在现代计算机系统中,程序的并发性已经变得越来越重要。多线程编程是一种利用计算机的多核处理器来提高程序性能的方法。C++是一种功能强大的编程语言,提供了丰富的多线程编程支持。本文将介绍如何利用C++多线程编程来提高程序的并发性。

什么是多线程编程?

多线程编程是指在一个程序中同时运行多个线程,每个线程执行不同的任务,从而加快程序的执行速度。多线程编程可以充分利用计算机的多核处理器,提高程序的并发性和响应能力。

C++多线程编程的基础

C++11引入了对多线程编程的支持,主要提供了以下几个组件:

  1. std::thread类:用于创建和管理线程的对象。
  2. std::mutex类:用于实现互斥访问,保护共享资源的完整性。
  3. std::condition_variable类:用于线程间的条件同步。
  4. std::atomic模板类:用于实现原子操作,确保数据的原子性。

如何使用C++进行多线程编程

下面是一个简单的示例,演示了如何使用C++进行多线程编程:

cppCopy code
#include <iostream>
#include <thread>
// 线程函数
void threadFunc(int id) {
    std::cout << "线程 " << id << " 正在执行" << std::endl;
}
int main() {
    const int numThreads = 5;
    std::thread threads[numThreads];
    // 创建并启动多个线程
    for (int i = 0; i < numThreads; ++i) {
        threads[i] = std::thread(threadFunc, i);
    }
    // 等待所有线程结束
    for (int i = 0; i < numThreads; ++i) {
        threads[i].join();
    }
    std::cout << "所有线程执行完毕" << std::endl;
    return 0;
}

在上面的示例中,首先定义了一个线程函数threadFunc,然后创建了多个线程,并分别调用threadFunc函数进行执行。最后,使用join()函数等待所有线程结束,并输出相应的提示信息。

多线程编程的注意事项

在进行多线程编程时,需要注意以下几点:

  1. 线程间的同步:使用互斥锁(std::mutex)和条件变量(std::condition_variable)等机制来保护共享资源的访问。
  2. 避免数据竞争:对于多个线程访问的共享数据,应当使用原子操作(std::atomic)来确保数据的原子性。
  3. 线程的生命周期:需要在合适的时机创建和销毁线程,避免创建过多的线程和资源浪费。
  4. 异常处理:在多线程编程中,要特别小心异常的处理,确保线程的正常结束。

结论

C++提供了丰富的多线程编程支持,通过合理地利用多线程,可以提高程序的并发性和响应能力。然而,在进行多线程编程时,需要注意线程的同步和数据的一致性,以及异常处理等问题。通过合理使用多线程编程技术,可以开发出更加高效和性能优越的程序。


当涉及到实际应用场景时,多线程编程可以为我们提供更高的并发性,从而提升程序的性能和响应能力。一个常见的应用场景是多线程下载器,它可以同时下载多个文件,并将它们合并成一个完整的文件。下面是一个示例代码,演示了如何使用C++进行多线程下载:

cppCopy code
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;  // 互斥锁用于保护共享资源
std::vector<std::string> files;  // 存储待下载的文件
std::vector<std::string> downloadedFiles;  // 存储已下载的文件
void downloadFile(const std::string& url) {
    // 模拟下载文件的操作
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::lock_guard<std::mutex> lock(mtx);  // 加锁
    downloadedFiles.push_back(url);  // 将下载完成的文件添加到已下载列表
    std::cout << "下载完成:" << url << std::endl;
}
int main() {
    // 添加待下载的文件
    files.push_back("http://www.example.com/file1.txt");
    files.push_back("http://www.example.com/file2.txt");
    files.push_back("http://www.example.com/file3.txt");
    
    std::vector<std::thread> threads;
    // 创建并启动多个线程进行文件下载
    for (const auto& file : files) {
        threads.emplace_back(std::thread(downloadFile, file));
    }
    
    // 等待所有线程结束
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 输出已下载的文件列表
    std::cout << "已下载的文件:" << std::endl;
    for (const auto& file : downloadedFiles) {
        std::cout << file << std::endl;
    }
    
    return 0;
}

在上面的示例中,首先定义了一个downloadFile函数,该函数模拟了下载文件的操作,并将已下载的文件添加到downloadedFiles列表。然后,添加了待下载的文件URL到files列表。接下来,创建了多个线程,并分别调用downloadFile函数进行下载。最后,使用join()函数等待所有线程结束,并输出已下载的文件列表。 通过多线程编程,该示例能够并行下载多个文件,从而提高下载速度和程序的并发性。请确保在实际应用中做好适当的异常处理和进一步的优化工作,以满足具体的需求。


下面是一个示例代码,演示了如何在C++中使用多线程技术来加速图像处理的过程。这个示例代码使用OpenCV库来加载图像,并使用多线程并行处理每个像素的灰度化操作。

cppCopy code
#include <iostream>
#include <thread>
#include <opencv2/opencv.hpp>
void grayscaleImage(const cv::Mat& input, cv::Mat& output, int startRow, int endRow) {
    for (int i = startRow; i < endRow; i++) {
        for (int j = 0; j < input.cols; j++) {
            cv::Vec3b color = input.at<cv::Vec3b>(i, j);
            uchar gray = (color[0] + color[1] + color[2]) / 3;
            output.at<uchar>(i, j) = gray;
        }
    }
}
int main() {
    // 加载图像
    cv::Mat inputImage = cv::imread("input.jpg", cv::IMREAD_COLOR);
    if (inputImage.empty()) {
        std::cerr << "无法加载图像文件" << std::endl;
        return -1;
    }
    // 创建输出图像
    cv::Mat outputImage(inputImage.size(), CV_8UC1);
    int numThreads = std::thread::hardware_concurrency();  // 获取可用的CPU核心数目
    std::vector<std::thread> threads(numThreads);
    int rowsPerThread = inputImage.rows / numThreads;
    // 创建并启动多个线程进行图像处理
    for (int i = 0; i < numThreads; i++) {
        int startRow = i * rowsPerThread;
        int endRow = (i == numThreads - 1) ? inputImage.rows : startRow + rowsPerThread;
        threads[i] = std::thread(grayscaleImage, std::ref(inputImage), std::ref(outputImage), startRow, endRow);
    }
    // 等待所有线程结束
    for (auto& thread : threads) {
        thread.join();
    }
    // 显示原始图像和灰度化后的图像
    cv::imshow("原始图像", inputImage);
    cv::imshow("灰度化后的图像", outputImage);
    cv::waitKey(0);
    return 0;
}

在上述示例代码中,首先,使用OpenCV库加载一张彩色图像。然后,创建一个与输入图像大小相同的输出图像。接下来,获取可用的CPU核心数目,并根据核心数目计算每个线程需要处理的行数。然后,创建一个包含多个线程的std::vector对象,并为每个线程指定其处理的行数范围。每个线程将执行grayscaleImage函数,该函数会将指定范围内的像素灰度化,并将结果存储在输出图像中。 最后,等待所有线程结束后,使用OpenCV的imshow函数显示原始图像和灰度化后的图像,并等待用户按下键盘后退出程序。 通过多线程并行处理,该示例代码能够加速图像的灰度化操作,提高了图像处理的效率和并发性。请确保在实际应用中做好适当的异常处理和进一步的优化工作,以满足具体的需求。

标签:std,int,编程,C++,线程,多线程
From: https://blog.51cto.com/u_15702012/8655076

相关文章

  • Java并发(十六)----线程八锁
    所谓的“线程八锁”其实就是看synchronized锁住的是哪个对象情况1:12或21都是有可能的,就看cpu先调度哪个线程@Slf4j(topic="c.Number")classNumber{  publicsynchronizedvoida(){    log.debug("1"); }  publicsynchronizedvoidb(){......
  • 查看进程线程的方法
    windows任务管理器可以查看进程和线程数,也可以用来杀死进程tasklist查看进程taskkill杀死进程netstat-ano|findstr端口号查看某个端口号下的进程taskkill/f/pid强制杀死某个进程linuxps-ef查看所有进程ps-fT-p<PID>查看某个进程(PID)的所有线程kill杀死进程......
  • C++入门:掌握基本语法和面向对象编程
    C++入门:掌握基本语法和面向对象编程C++是一种通用的、高级的编程语言,广泛应用于开发各种应用程序。对于初学者来说,掌握C++的基本语法和面向对象编程是一个重要的起点。本篇博客将介绍C++的基本语法和面向对象编程的基本概念。了解C++的基本语法注释在C++中,你可以使用两种方式添加注......
  • Redis为什么是单线程及高并发的原因
    Redis的高并发和快速原因1.redis是基于内存的,内存的读写速度非常快2.redis是单线程的,省去了很多上下文切换线程的时间3.redis使用多路复用技术,可以外理并发的连接。非阻塞I0内部实现采用epol,采用了epol+自己实现的简单的事件框架。epol中的读、写、关闭、连接都转化成了事件,然后......
  • C++聊天集群服务器5
    一、服务器异常处理函数​ 这部分主要处理服务器异常退出时,用户的在线状态还是online不会改变,因此需要修改。由于是需要对用户进行操作,因此我们在user表的数据操作类添加重置用户状态函数。​ 在usermodel.hpp添加后:#ifndefUSERMODEL_#defineUSERMODEL_#include"user.hpp......
  • C++学习笔记——函数探幽
    C++内联函数内联函数是一种用空间换时间的技术,是C++提高程序运行速度做的改进。运行程序时操作系统将指令载入计算机内存中,并逐条执行这些指令,遇到循环或分支时向前或向后跳转到特定的地址(每条指令都有特定的内存地址)。常规函数也是如此,在调用常规函数时立即存储该指令的地址......
  • error: Microsoft Visual C++ 14.0 or greater is required
    1、错误背景python在安装aiohttp库时,出现MicrosoftVisualC++14.0orgreaterisrequired的提示:2、解决方案按照错误提示,访问https://visualstudio.microsoft.com/visual-cpp-build-tools/,下载生成工具:执行下载的exe执行文件:选择使用C++桌面开发,选......
  • .NET Core|--调用C++库|--docker环境下让web api应用程序调用C++类库
    前言#前提安装docker环境~启动docker~#多说一句,为什么我要搞这个一个镜像,既包含gcc开发环境,又包含.NET开发环境我的api应用程序是基于.NET写的,但是我的这个api程序,又要调用c++的一些东西,特别是涉及一些画图之类的,所以就需要gcc的开发环境,最终搞了这么一......
  • 进程,线程,协程
    1、进程进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等......
  • .net core 使用Task多线程执行任务,限制线程数量,并等待所有任务结束
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceDataService.ETL_ApiData{publicclassMultiTask{///<summary>///最大线程数量///</summa......