C++11提供的并发编程

C++并发编程(C++11) C++11有了std::thread 以后,可以在语言层面编写多线程程序了,直接的好处就是多线程程序的可移植性得到了很大的提高。 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic>,<thread>,<mutex>,<condition_variable>和<future>。 <atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_flag,. 阅读详情

C++11 提供的并发编程

在C++11之前,如果想要实现并发编程,就需要使用具体平台提供的并发编程相关的库,非常的不方便,而且还不支持跨平台。在C++11之后,终于在语言层面有了并发编程的支持。包括线程控制、互斥锁、条件变量、区域锁(lockguard)、原子操作、异步等。

线程控制

  • C++11封装了一套线程库,位于thread文件中。

  • 使用std::thread类创建线程,构造thread对象时传入一个可调用对象作为参数,如果有 参数,同时传入参数。构造完成后,新的线程被创建,同时执行该可调用对象。

  • std::thread默认构造函数构造的对象不关联任何线程,判断一个thread对象是否关联线程可以用joinable()接口。

  • joinable的对象析构前,要么用join()等待结束,要么用detach()接触与线程的关联。

  • thread类没有拷贝构造和拷贝赋值,可以move,没有两个thread对象会表示同一线程。

  • c++11创建线程、分离线程、回收线程、获取线程id

#include <thread>
#include <iostream>>
using namespace std;

void ThreadFunc(int nThreadNum)
{
	cout << "INFO: Num is " << nThreadNum << endl;
}

int main()
{
	thread TestThread(ThreadFunc, 1);
	thread TestThread_detach(ThreadFunc, 2);
	TestThead_detach.detach();
	cout << TestThread.get_id() << endl;
	
	TestThread.join();
	return 0;
}

互斥锁

  • 通过mutex可以方便的对临界区加锁,std::mutex定义在mutex头文件,用来避免多个线程同时访问。
  • 提供lock、trylock、unlock
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

void AddCount(mutex &mutexTest, int &nCount)
{
	for (int i = 0; i < 1000; ++i)
	{
		mutexTest.lock();
		++nCount;
		mutexTest.unlock();
	}
}

int main()
{
	thread arrThreads[5];
	mutex mutexTest;
	int nCount = 0;

	for (auto& threadIte : arrThreads)
	{
		threadIte = thread(AddCount, ref(mutexTest), ref(nCount));
	}
	for (thread& threadIte : arrThreads)
	{
		threadIte.join();
	}
	cout << nCount << endl;

	return 0;
}

  • 同时还提供了其他几种熟悉的互斥锁
    • std::mutex,最常用,普遍的互斥量(默认属性),
    • std::recursive_mutex ,允许同一线程使用recursive_mutext多次加锁,然后使用相同次数的解锁操作解锁。mutex多次加锁会造成死锁
    • std::timed_mutex,在mutex上增加了时间的属性。增加了两个成员函数try_lock_for(),try_lock_until(),分别接收一个时间范围,再给定的时间内如果互斥量被锁主了,线程阻塞,超过时间,返回false。
    • std::recursive_timed_mutex,增加递归和时间属性

lock_guard

  • 有作用域的mutex ,让 程序更稳定,防止死锁

  • 类模板std::lock_guard是mutex封装器,通过便利的RAII机制在其作用域内占有mutex。

  • 创建lock_guard对象时,它试图接收给定mutex的所有权。当程序流程离开创建lock_guard对象的作用域时,lock_guard对象被自动销毁并释放mutex,lock_guard类也是不可复制的。

  • 一般,需要加锁的代码段,我们用{}括起来形成一个作用域,括号的开端创建lock_guard对象,把mutex对象作为参数传入lock_guard的构造函数即可,比如上面的例子加锁的部分,我们可以改写如下

std::thread t([&](){
	for(int i=0;i<10000;i++)
	std::lock_guard<mutex> guard(mtx);
	++num;
	}
})

进入作用域,临时对象guard创建,获取mutex控制权(构造函数里调用了mutex的lock接口),离开作用域,临时对象guard销毁,释放了mutex(析构函数里调用了unlock接口)

条件变量

条件不满足,线程被阻塞。一个线程等待某一变量的成立而阻塞,另一线程使该变量变化而使上一线程成立,同时发送信号(notify)唤醒wait的线程。

  • 接口
    • notify_one通知一个等待的线程
    • notify_all通知所有等待的线程
    • wait 阻塞当前线程,直到条件变量被唤醒
    • wait_for 阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后
    • wait_until 阻塞当前线程,直到条件变量被唤醒,或直到抵达指定时间点
    • native_handle 返回原生句柄
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // 等待直至 main() 发送数据
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});
 
    // 等待后,我们占有锁。
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // 发送数据回 main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // 通知前完成手动解锁,以避免等待线程才被唤醒就阻塞(细节见 notify_one )
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // 发送数据到 worker 线程
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // 等候 worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
}

原子操作

C++11起提供了atomic,可以使用它定义一个原子类型。

  • 为什么要定义一个原子类型?
    举个例子,int64_t类型,在32位机器上为非原子操作。更新时该类型的值时,需要进行两步操作(高32位、低32位)。如果多线程操作该类型的变量,且在操作时未加锁,可能会出现读脏数据的情况。

解决该问题的话,加锁,或者提供一种定义原子类型的方法。

#include<atomic>
#include<iostream>
int main(){
  std::atomic<int64_t> value;//定义一个原子对象
  int64_t x=10;
  value.store(x);//将x存入该原子对象中
  value++;//使用原子对象特化的自增
  int64_t y=value.load(std::memory_order_relaxed);//取出原子对象中的值
  std::cout<<y<<std::endl;

}


  • 其他原子类型相关操作
特化成员函数说明
fetch_add原子地将参数加到存储于原子对象的值,并返回先前保有的值
fetch_sub原子地进行参数和原子对象的值的逐位与,并获得先前保有的值
fetch_or原子地进行参数和原子对象的值的逐位或,并获得先前保有的值
fetch_xor原子地进行参数和原子对象的值的逐位异或,并获得先前保有的值
operator++令原子值增加一
operator++(int)令原子值增加一
operator–令原子值减少一
operator–(int)令原子值减少一

异步

  • 异步操作的主要目的是让调用方法的主线程不需要同步等待调用函数,从而可以让主线程继续执行它下面的代码。因此异步操作无须额外的线程负担,使用回调的方式进行处理。在设计良好的情况下,处理函数可以不必或者减少使用共享变量,减少了死锁的可能。当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。
  • C++11中的异步操作主要有std::future、std::async、std::promise、std::packaged_task。
    • std::async最简洁,返回值就是future对象,任务可以在调用std::async结束后立即执行,也可以延后执行,使用future来控制
    • std::packaged_task把future对象的创建和任务的执行分割开来,提升了自由度,任务可以放到指定线程中去运行
    • std::promise灵活性最高,std::async和std::packaged_task都必须等到任务执行完毕后才能在future对象里拿到返回值,std::promise则可以在任务执行的任意时候都能拿到返回值,不必等到任务执行结束。

async

  • async 异步可以让耗时的操作不影响当前主进程的执行,而是单独的启动一个新的线程来运行任务.

  • std::async执行的任务可以运行在单独线程里,也可以不运行在单独线程里,如果是立即执行则会开一个线程去执行,如果是延后执行,则会在调用任务的线程里阻塞执行。

  • 立即执行,开一个线程去执行

  • 如果是立即执行,那么还需要注意future对象的析构问题。
    如果要析构std::async返回的future对象,那么future对象的析构函数会阻塞当前线程,直到任务执行结束

#include <future>
#include <iostream>


bool myfunc(int data1, int data2)
{
    std::cout << "myfunc id: " << std::this_thread::get_id() << "\n";
    
    if (data1+data2 > 100)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    std::cout << "main id: " << std::this_thread::get_id() << "\n";
    
    std::future<bool> fu = std::async(myfunc, 100, 200); // 100和200是myfunc需要的参数
    
    // 阻塞等待
    fu.get();

    return 0;
}

  • 延后执行,在调用get后在本线程中阻塞执行。
#include <future>
#include <iostream>


bool myfunc(int data1, int data2)
{
    std::cout << "myfunc id: " << std::this_thread::get_id() << "\n";
    
    if (data1+data2 > 100)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    std::cout << "main id: " << std::this_thread::get_id() << "\n";
    
    std::future<bool> fu = std::async(std::launch::deferred, myfunc, 100, 200); // 100和200是myfunc需要的参数
    
    // 等待1秒
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 阻塞等待
    fu.get();

    return 0;
}

package_task

  • std::packaged_task,相比于std::async,std::packaged_task自由度更高,而且也没有future对象析构阻塞的问题。分割了future对象的创建和任务的执行,执行任务可以显示地指定某个线程去做,不像std::async是背后做的
#include <future>
#include <iostream>


bool myfunc(int data1, int data2)
{    
    // 等待1秒
    std::this_thread::sleep_for(std::chrono::seconds(1));

    if (data1+data2 > 100)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    std::packaged_task<bool(int, int)> task(myfunc);

    std::future<bool> fu = task.get_future();
    
	// 必须要使用std::move把task转成右值
    std::thread t(std::move(task), 100, 200); // 100和200是myfunc需要的参数
    
	// 调用get进行阻塞等待
    std::cout << fu.get() << "\n";
    
    t.join();

    return 0;
}


promise

  • std::promise,相比于前2个,std::promise不需要等到任务结束就可以拿到future对象里的值,而且自由度最高,可以根据需要来决定返回值类型,不必是任务结束时的返回值。另外,std::promise只是个异步结果的提供者,不像前2者可以传递任务进来。

  • 在主线程中初始化一个可以传递string的promise,获取他的future,开启一个新线程,把promise传进去,这样就可以在这个线程函数中给promise放置信息,在主线程中,可以不用等这个线程函数结束就用future的get获取它放置的信息。另外可以将promise的类型设为void,只起到通知作用。

#include <future>
#include <iostream>
#include <string>


bool myfunc(std::promise<std::string> pro, int data1, int data2)
{    
    // 等待1秒
    std::this_thread::sleep_for(std::chrono::seconds(1));

    pro.set_value("hello");

    // 等待2秒
    std::this_thread::sleep_for(std::chrono::seconds(2));

    if (data1+data2 > 100)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    std::promise<std::string> pro;

    std::future<std::string> fu = pro.get_future();
	
    // 必须使用std::move把pro转成右值,之后pro就不能再被使用
    std::thread t(myfunc, std::move(pro), 100, 200);

    std::cout << fu.get() << "\n";
    
    t.join();

    return 0;
}


  • 利用主线程控制线程函数,可以把promise的future传给要执行的线程函数,在主线程中设置promise的值,在线程函数中的future get
#include <future>
#include <iostream>
#include <string>


bool myfunc(std::future<void> fu, int data1, int data2)
{    
    fu.get();

    std::cout << "DDD\n";

    if (data1+data2 > 100)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    std::promise<void> pro;

    std::future<void> fu = pro.get_future();

    std::thread t(myfunc, std::move(fu), 100, 200);

    // 等待1s
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 进行通知
    pro.set_value();
    
    t.join();

    return 0;
}


参考文档

C++异步操作三种方式的区别
C++11中的异步操作
C++多线程编程

后记

日暮乡关走歧途,朝朝暮暮滂沱路
寒山远方望金台,伶仃之余谈风生

C++ 并发编程(C++11 到 C++17 ) 为什么要并发编程大型的软件项目常常包含非常多的任务需要处理。例如:对于大量数据的数据流处理,或者是包含复杂GUI界面的应用程序。如果将所有的任务都以串行的方式执行,则整个系统的效率将会非常... 阅读详情

相关推荐

[C++11多线程实现]:并发编程的终极指南

希望读者通过本文的介绍和实践,能够掌握C++11多线程的基本概念、使用方法和一些常用技巧,从而加深对并发编程的理解和应用。本文将介绍C++11多线程的基本概念、使用方法和一些常用技巧,帮助读者掌握并发编程的核心思想和基本技能。std::condition_variable类代表一个条件变量,它的wait()和notify()方法可以分别用来等待和唤醒线程。为了保证线程的安全性,我们需要遵循一些规则和原则,如避免共享数据、使用互斥锁和条件变量、尽量减少锁的持有时间等。

CyberNova的博客 191

【C++11】C++并发编程

【C++11】C++并发编程 前言 首先需要说明,本博客的主要内容参考自Forhappy && Haippy博主的分享,本人主要是参照博主的资料进行了学习和总结,并适当的衍生或补充了相关的其他知识内容。 C++11有了std::thread 以后,可以在语言层面编写多线程程序了,直接的好处就是多线程程序的可移植性得到了很大的提高。 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是,和。 :该头文主要声明了两个类, std::atomic 和 std::atomic_flag

qq_43331089的博客 1387

深入理解现代C++并发编程

本文深入探讨了《现代C++并发编程》一书的核心内容,包括C++11和C++14的基础知识、C++17的并行算法、协程、案例研究、内存模型、多线程技术等。通过对书中每个章节的详细解读,我们不仅能够了解现代C++在并发方面的强大功能,还能掌握如何有效利用这些并发工具来提升软件性能。

weixin_35757531的博客 370

C++11 并发指南系列

本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C++11 并发指南二(std::thread 详解)(本章计划 1-2 篇,已完成 1 篇) C++11 并发指南三(std::mutex 详解)(本章计划 1-2 篇,已完成 2 篇) C++11 并发指南三(std::mutex 详解) C++11 并发指南三(Lock 详解) C++11 并发指

Augusdi的专栏 874

现代C++并发编程的全貌

本文旨在为读者提供对《现代C++并发编程》一书的深入解读。书籍不仅介绍了C++从C++11到C++23中的并发特性,还详尽地讨论了并发编程的陷阱和如何应对。作者通过丰富的代码示例和实践经验,带领读者从基础到高级概念,逐步深入理解并发编程。特别地,书中还强调了C++未来可能引入的新特性,如执行器和事务内存,展现了并发编程在C++中的广阔前景。

weixin_42561464的博客 452

LAP-D协议概述

Q.921协议由称为LAPD(链路访问协议-D通道),与HDLC的关系密切,它是在ISDN D通道上使用的数据链路协议。 注:http://www.freesoft.org/CIE/Topics/125.htm LAP-D的帧格式 标志、位填充技术和FCS校验计算与HDLC一致。 16位的地址包括C/R字段、SAPI(服务访问点标识)和TEI(端点标识)。TEI用于区分使用相同ISDN...

系统运维 1914

探索高效的并发编程:cpp11thread 库

探索高效的并发编程:cpp11thread 库 在现代软件开发中,多线程编程已成为性能优化和资源管理的重要手段。 是一个基于 C++11 标准库的轻量级线程库,它为开发者提供了更简单、直观的方式来管理和操作线程,旨在提高并发代码的可读性和可靠性。 项目简介 cpp11thread 是一个开源项目,其目标是封装 C++11 的 std::thread API,提供一些方便实用的扩展功能。该项目由 h...

gitblog_00071的博客 502

MATLAB 论文复现——基于虚拟储能的电动汽车充放电调度策略及激励评价

文章基于虚拟储能聚合体仿真模型优化电动汽车充放电调度,并采用复合权重评价电动汽车的充电激励。根据电动汽车灵活性和系统稳定性衡量其贡献大小,并通过模糊推理系统模拟用户的充电意愿,实现对电动汽车充电的引导和优化。[1]陈朔,胡昊,方慧敏,等.基于虚拟储能的电动汽车充放电调度策略及激励评价[J/OL].系统仿真学报,1-12[2024-07-24].https://doi.org/10.16182/j.issn1004731x.joss.23-1316.基于虚拟储能的电动汽车充放电调度策略及激励评价。

sjr1478的博客 363

cpp-channel:为C++11带来Go风格的并发编程

cpp-channel:为C++11带来Go风格的并发编程 项目介绍 cpp-channel 是一个为 C++11 提供类似 Go 语言风格的并发编程模型的库。它通过 cpp::channel 类型的通道,使得在多个线程之间进行通信变得简单而高效。这个库的设计理念来源于 Go 语言的并发模型,它通过通道(channel)的概念来简化线程间的数据传递,避免了传统多线程编程中的复杂性和不确定性。 项目...

gitblog_00489的博客 986

SecureCRT多种配色方案配置文件

位置 C:\Users%USERNAME%\AppData\Roaming\VanDyke\Config\Global.ini S:"SecureCRT Tab State"=1,1,1,0,0 S:"SecureFX Local Tab State"=1,-1,200 D:"Max Chat Window History"=000000c8 D:"Active Window Alpha Transparency"=000000f0 D:"Save Keymaps As Unicode"=00000000

神棍之路 3708

U盘重装Win10系统

准备工作 准备一个8G或8G以上U盘(32G以内) 请备份好u盘里的资料,在制作过程中会格式化硬盘 请备份好要安装系统的盘的资料,安装时也会对该盘内容进行格式化。 将u盘插入电脑usb接口中,尽可能的插入usb3.0的接口,这样下载和安装速度会更快。 1.到微软官网下载安装包 浏览器输入:微软官网下载win10 懒人请复制粘贴:https://www.microsoft.com/zh-cn/software-download/windows10 ​ 打开之后的界面: 2.下载Media Creat.

Cici$的博客 2115

【亲测免费】 探索 `cpp.react`:C++中的响应式编程库

在现代软件开发中,响应式编程已经成为一种流行的范式,它简化了异步数据流的处理,使开发者能够更高效地编写可维护的代码。`cpp.react`()是一个开源项目,将这种概念引入C++世界,旨在为C++开发者提供一套强大的工具集,用于构建动态、事件驱动的应用程序。 ## 技术分析 `cpp.react` 基于C++11/14标准,利用其特性如lambda表达式和智能指针等,实现了对异步操作和数据流的

gitblog_00012的博客 413

Emscripten安装(wasm编译)

5:配置对应环境变量--替换成自己对应的安装路径(2025最新的Emscripten工具链默认使用LLVM/WebAssembly标准工作流,java依赖已经移除了,所以以下java环境不配,需要使用java的手动添加即可---->emsdk install java-8-152-64bit。3:下载相应的依赖库---->emsdk install latest(我这里下的是最新的,如果有指定版本,把latest替换成版本号即可)6:测试是否成功---> emcc- v/em++ -v。

qq_31578301的博客 554

C++并发编程(C++11到C++17)

为什么要并发编程大型的软件项目常常包含非常多的任务需要处理。例如:对于大量数据的数据流处理,或者是包含复杂GUI界面的应用程序。如果将所有的任务都以串行的方式执行,则整个系统的效率将会非常...

青春不老,奋斗不止! 2224

全球建筑物提取数据集(免费下载):微软/GlobalMLBuildingFootprints

这个是GitHub上的开源数据集: https://github.com/microsoft/GlobalMLBuildingFootprints 介绍 必应地图正在世界各地发布开放式建筑足迹。我们从 2014 年到 2021 年间的 Bing Maps 图像中检测到了 7.77 亿座建筑物,包括 Maxar 和 Airbus 的图像。数据可在 ODbL 下免费下载和使用。该数据集补充了我们的其他版本。 包括的地区 执照 此数据由 Microsoft 根据Open Dat..

此星光明博客 6289

点云去噪:基于点云拟合的方法

点云处理是计算机视觉中的重要任务之一,而点云去噪是点云处理的关键步骤之一。在实际应用中,由于采集设备的噪声、运动估计误差或者环境干扰等因素,点云数据中常常包含有噪声点,这些噪声点会对后续的点云分析和处理造成不良影响。一种简单的方法是计算点到拟合曲面的距离,并将距离超过某个阈值的点定义为噪声点,进行过滤。一种简单的方法是计算点到拟合曲面的距离,并将距离超过某个阈值的点定义为噪声点,进行过滤。该方法通过拟合点云数据的曲面模型,对噪声点进行识别和过滤,从而得到更加干净的点云数据。

AuSwift的博客 638

C++11并发编程指南

feikudai8460的博客 365

数据库课程案例——电力公司收费管理系统分析与实践,完整带SQL语句

某电力公司收费管理信息系统实现客户信息、用电类型(类别号、类别名、电价)及业务员管理;实现客户用电信息管理(客户号、月份、用电类别号、用电度数);实现客户费用管理(客户号、月份、费用、收费标志),收费标志的默认值为“未收”;实现收费登记(客户、月份、应收费用、实收费用、业务员),并自动修改收费标志(用触发器实现);创建触发器,实现收费时自动更加应收费用和实收费用,计算本次结余,然后修改客户信息表中的结余金额;创建存储过程统计指定月份应收费用和实收费用;创建存储过程查询指定月份未交费的用户信息,以便崔费;创建

qq_44242804的博客 2761

C++并发编程 C++11

C++并发编程(C++11)_菜鸟502的博客-优快云博客_c++并发编程

Mr.π的博客 210

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【亲测免费】 Concurrency-with-Modern-C++:掌握C++并发编程的核心利器

Concurrency-with-Modern-C++:掌握C++并发编程的核心利器 项目介绍 在现代软件开发中,并发编程是提高程序性能和响应速度的关键技术之一。由Rainer Grimm所著,陈晓伟翻译的《Concurrency-with-Modern-C++》为C++开发者提供了一场关于并发性的深度学习之旅。本书旨在帮助开发者理解和掌握C++中的并发概念和技术,从而提升编程能力和软件质量。 项...

gitblog_00374的博客 911

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++ 11并发

http://www.cnblogs.com/hujian/archive/2012/12/10/2810788.html 【原】C++ 11并发     在C++ 11中,可以使用异步任务async和future配合来完成一些轻量级的并发编程工作。async使用比较简单,只需要传入要并发执行的函数即可。future用于占位,以获取并发执行的函数的结果;调用其get

any 804

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++并发编程实战 源码 (C++ Concurrency in Action)

C++并发编程实战 源码 (C++ Concurrency in Action) 【下载地址】C并发编程实战源码CConcurrencyinAction 本仓库提供了《C++并发编程实战》(C++ Concurrency in Action)一书的源码资源。这些源码是书中示例代码的完整实现,帮助读者更好地理解和实践C++...

gitblog_09760的博客 648

好教程推荐系列:《C++并发编程指南》《高性能并行编程与优化》

这本书是国内非常稀缺的用中文写作的C++11的并发编程书籍。 https://github.com/forhappy/Cplusplus-Concurrency-In-Practice

$firecat利白的代码足迹$ 3419

探索C++并发编程的奥秘:《C++并发编程实战》源码推荐

探索C++并发编程的奥秘:《C++并发编程实战》源码推荐 【下载地址】C并发编程实战源码CConcurrencyinAction 本仓库提供了《C++并发编程实战》(C++ Concurrency in Action)一书的源码资源。这些源码是书中示例代码的完整实现,帮助读者更好地理解和实践C++并发编程的相关概念和技术...

gitblog_09715的博客 384

《C++ 并发编程》- 第1章 你好,C++的并发世界

《C++ 并发编程》- 第1章 你好,C++的并发世界 本文是《C++ 并发编程》的第一章,感谢人民邮电出版社授权并发编程网发表此文,版权所有,请勿转载。该书将于近期上市。 本章主要内容 何谓并发和多线程 为什么要在应用程序中使用并发和多线程 C++并发支持的发展历程 一个简单的C++多线程程序是什么样的 这是C++用户的振奋时刻。距1998年初始的C++标准发布1

洛阳纸迷 893

C++语言的并发编程

并发编程是指在同一时间段内处理多个计算任务的能力。并发通常分为两个层次:一个是"多任务",即在一个程序中同时处理多个任务;另一个是"并行",即在多个处理器上同时执行多个任务。并发编程的目的在于提高程序的响应性和利用资源的效率。

2501_90467973的博客 541
上一篇: 【linux服务器编程学习】10.多线程编程
下一篇: 使用python streamlit库快速创建一个购物网站
Sweler*19
博客等级 码龄7年 65粉丝 56原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值