当前位置: 首页 > news >正文

C++并发编程完全指南:从基础到实践

在当今多核处理器普及的时代,充分利用硬件并发能力已成为高性能编程的关键。C++11引入的现代并发编程支持使得开发者能够以标准化、可移植的方式编写多线程程序。本文将全面介绍C++并发编程的各个方面,从基础概念到实际应用,帮助您掌握这一重要技能。

一、并发编程概述

1.1 为什么需要并发编程

随着处理器核心数量的增加,单线程程序已经无法充分利用现代硬件资源。并发编程主要解决以下问题:

  • 性能提升:通过并行处理加速计算密集型任务

  • 响应性增强:保持用户界面响应同时执行后台操作

  • 资源利用:高效利用多核CPU和I/O等待时间

  • 任务分离:将复杂系统分解为独立协作的组件

1.2 并发与并行的区别

虽然经常混用,但这两个概念有本质区别:

  • 并发(Concurrency):多个任务交替执行,看似同时进行

  • 并行(Parallelism):多个任务真正同时执行,需要多核支持

C++标准库提供了同时支持这两种模式的统一接口。

二、线程基础

2.1 线程创建与管理

C++通过std::thread类提供线程支持,基本用法如下:

#include <iostream>
#include <thread>void thread_task() {std::cout << "Hello from thread " << std::this_thread::get_id() << "\n";
}int main() {std::thread t(thread_task);std::cout << "Main thread ID: " << std::this_thread::get_id() << "\n";t.join();return 0;
}

关键点:

  • 线程在构造时立即开始执行

  • 必须明确选择join()detach()

  • 主线程结束时会终止整个程序

2.2 线程参数传递

线程函数支持任意数量和类型的参数:

void print_sum(int a, int b) {std::cout << a + b << "\n";
}int main() {std::thread t(print_sum, 3, 4);t.join();
}

参数总是按值传递,如需传递引用必须使用std::ref包装:

void modify(int& x) {x *= 2;
}int main() {int value = 5;std::thread t(modify, std::ref(value));t.join();std::cout << value; // 输出10
}

2.3 线程生命周期管理

正确处理线程生命周期至关重要:

std::thread create_thread() {return std::thread([]{std::cout << "New thread\n";});
}int main() {std::thread t = create_thread();if (t.joinable()) {t.detach(); // 或t.join()}// 错误示例:线程未join或detach// std::thread t2([]{...});// t2的析构函数会调用std::terminate
}

三、同步机制

3.1 互斥量(Mutex)

互斥量是最基本的同步原语,C++提供多种变体:

类型特性
std::mutex基本互斥量
std::recursive_mutex可重入互斥量
std::timed_mutex支持超时锁定
std::shared_mutex读写锁(C++14)

基本用法:

std::mutex mtx;
int shared_data = 0;void increment() {mtx.lock();++shared_data;mtx.unlock();
}// 更安全的RAII方式
void safe_increment() {std::lock_guard<std::mutex> lock(mtx);++shared_data;
}

3.2 条件变量(Condition Variable)

条件变量允许线程等待特定条件成立:

std::mutex mtx;
std::condition_variable cv;
bool ready = false;
std::string data;void worker() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return ready; });std::cout << "Processing: " << data << "\n";
}int main() {std::thread t(worker);// 准备数据{std::lock_guard<std::mutex> lock(mtx);data = "Sample data";ready = true;}cv.notify_one();t.join();
}

3.3 原子操作

对于简单数据类型,原子操作比互斥量更高效:

#include <atomic>std::atomic<int> counter(0);void increment_atomic() {for (int i = 0; i < 1000; ++i) {++counter;}
}int main() {std::thread t1(increment_atomic);std::thread t2(increment_atomic);t1.join();t2.join();std::cout << counter; // 总是2000
}

四、高级并发特性

4.1 异步任务(std::async)

std::async提供更高层次的异步执行抽象:

#include <future>int compute() {std::this_thread::sleep_for(std::chrono::seconds(1));return 42;
}int main() {auto future = std::async(std::launch::async, compute);// 执行其他工作...std::cout << "Result: " << future.get() << "\n";
}

启动策略:

  • std::launch::async:立即异步执行

  • std::launch::deferred:延迟到get()/wait()时执行

4.2 并行算法(C++17)

C++17引入了并行标准算法:

#include <algorithm>
#include <vector>int main() {std::vector<int> data(1000000);// 并行排序std::sort(std::execution::par, data.begin(), data.end());// 并行变换std::transform(std::execution::par,data.begin(), data.end(), data.begin(),[](int x) { return x * 2; });
}

执行策略:

  • std::execution::seq:顺序执行

  • std::execution::par:并行执行

  • std::execution::par_unseq:并行且向量化

五、并发设计模式

5.1 生产者-消费者模式

#include <queue>std::mutex mtx;
std::condition_variable cv;
std::queue<int> msg_queue;void producer() {for (int i = 0; i < 10; ++i) {{std::lock_guard<std::mutex> lock(mtx);msg_queue.push(i);}cv.notify_one();std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return !msg_queue.empty(); });int msg = msg_queue.front();msg_queue.pop();lock.unlock();if (msg == -1) break; // 终止信号std::cout << "Received: " << msg << "\n";}
}

5.2 线程池实现

基本线程池结构:

class ThreadPool {std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop = false;public:ThreadPool(size_t threads) {for (size_t i = 0; i < threads; ++i) {workers.emplace_back([this] {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queue_mutex);condition.wait(lock,[this]{ return stop || !tasks.empty(); });if (stop && tasks.empty()) return;task = std::move(tasks.front());tasks.pop();}task();}});}}template<class F>void enqueue(F&& f) {{std::unique_lock<std::mutex> lock(queue_mutex);tasks.emplace(std::forward<F>(f));}condition.notify_one();}~ThreadPool() {{std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (std::thread &worker : workers)worker.join();}
};

六、性能考量与最佳实践

  1. 避免虚假共享:将频繁写入的变量放在不同缓存行

    struct alignas(64) CacheLineAligned {int data;
    };
  2. 锁粒度:保持锁的粒度尽可能小

  3. 无锁编程:在性能关键路径考虑无锁数据结构

  4. 线程数量:通常等于硬件线程数,可通过std::thread::hardware_concurrency()获取

  5. 异常安全:确保锁在异常情况下也能释放

  6. 死锁预防

    • 按固定顺序获取多个锁

    • 使用std::lock同时获取多个锁

    • 避免在持有锁时调用用户代码

七、C++20新增特性

  1. 信号量(Semaphore)

    #include <semaphore>
    std::counting_semaphore<10> sem(0);void worker() {sem.acquire();// 执行工作...
    }void post() {sem.release();
    }

  2. 闩(Latch)和屏障(Barrier)

    std::latch completion_latch(5); // 需要5次count_down()
    std::barrier sync_point(3);    // 每3个线程到达后继续
  3. 协程支持:为异步编程提供新范式

结语

C++并发编程是一个庞大而复杂的主题,本文涵盖了从基础线程操作到高级设计模式的广泛内容。掌握这些知识后,您将能够:

  1. 构建高效的多线程应用程序

  2. 设计线程安全的数据结构

  3. 避免常见的并发陷阱

  4. 充分利用现代硬件资源

记住,并发编程的首要目标是正确性,其次才是性能。始终优先考虑代码的安全性和可维护性,只有在必要时才进行复杂的优化。

随着C++标准的演进,并发支持仍在不断增强。建议持续关注新特性,如C++23中预计加入的更多并行算法和增强的协程支持。

相关文章:

C++并发编程完全指南:从基础到实践

在当今多核处理器普及的时代&#xff0c;充分利用硬件并发能力已成为高性能编程的关键。C11引入的现代并发编程支持使得开发者能够以标准化、可移植的方式编写多线程程序。本文将全面介绍C并发编程的各个方面&#xff0c;从基础概念到实际应用&#xff0c;帮助您掌握这一重要技…...

vue3 element-plus 输入框回车跳转页面问题处理

问题描述&#xff1a; 当页面搜索条件只有一个的情况下&#xff0c;输入框不管有没有值&#xff0c;回车后会跳转页面 解决办法&#xff0c;给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…...

从0开始学习大模型--Day03--Agent规划与记忆

规划&#xff08;planning&#xff09; 规划&#xff0c;可以为理解观察和思考。如果用人类来类比&#xff0c;当我们接到一个任务&#xff0c;我们的思维模式可能会像下面这样: 1、首先会思考怎么完成这个任务。 2、然后会审视手头上所拥有的工具&#xff0c;以及如何使用这…...

DevExpressWinForms-AlertControl-使用教程

文章目录 AlertControl-使用教程一、将 AlertControl 添加到 Form二、编辑 AlertControl 的 HtmlTemplateHTML Template Editor介绍编辑HTML Template 三、使用AlertControl弹出AlertAlert中的按钮事件获取 Alert 标题等信息向Alert传递参数 总结源码 AlertControl-使用教程 一…...

配电站室智能巡检:机器人 VS 固定摄像头,谁更胜一筹?

在配电站室巡检领域&#xff0c;传统人工巡检正逐渐被智能化手段取代。其中&#xff0c;机器人巡检与固定摄像头巡检成为两大热门选择。那么&#xff0c;它们究竟谁更胜一筹&#xff1f; 一、机器人巡检与固定摄像头巡检的对比 目前人工巡检工作主要以查看表计&#xff0c;设…...

脑图谱:脑机接口的必由之路——技术突破与产业转化的系统性思考

一、三维发育小鼠大脑图谱框架(DevCCF) 1. 技术原理与核心创新 DevCCF框架由宾夕法尼亚州立大学团队主导开发,其技术突破体现在多模态数据融合与跨尺度分析能力的革新: 多模态成像整合:采用高分辨率MRI(空间分辨率50-100μm)捕捉全脑宏观结构动态变化,结合光片荧光显…...

【网络编程】二、UDP网络套接字编程详解

文章目录 前言Ⅰ. UDP服务端一、服务器创建流程二、创建套接字 -- socketsocket 属于什么类型的接口❓❓❓socket 是被谁调用的❓❓❓socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓三、绑定对应端口号、IP地址到套接字 -- bind四、数据的发送和接收 -- `sendto…...

缓存替换算法与存储器管理的分页、分段、段页式管理联系

缓存替换算法与存储器管理的分页、分段、段页式管理在目标和机制上存在相似性&#xff0c;均涉及高效资源分配和地址映射&#xff0c;但应用层级和具体场景不同。以下是它们的联系与区别分析&#xff1a; 1. 核心联系&#xff1a;资源管理的共性 替换策略的必要性 无论是缓存&a…...

AI大模型基础设施:NVIDIA GPU和AMD MI300系列的区别

本文将从架构设计、性能、内存、功耗、软件生态、价格与性价比、供应链与市场表现等多个维度对比英伟达的GPU&#xff08;以H100为代表&#xff09;和AMD的Instinct MI300系列处理器&#xff08;以MI300X GPU和MI300A APU为主&#xff09;。以下是详细分析&#xff1a; 1. 架构…...

基于Matlab实现耦合模理论仿真程序

耦合模理论&#xff08;Coupled Mode Theory&#xff0c;简称CMT&#xff09;是一种广泛应用于光子学、微波工程和电子学领域的理论框架&#xff0c;用于分析和理解多模系统的相互作用。 耦合模理论主要研究两个或多个模式之间的能量交换&#xff0c;这些模式可以是电磁波、声…...

图片文件转base64存储在数据库

以下是将文件转换为Base64编码字符串的Java代码&#xff1a; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Base64;public class ImageToBase64 {/*** 将图片文件转换为Base64字符串* param filePath 图片文件路径* r…...

我的世界云端服务器具体是指什么?

我的世界云端服务器是指一种基于互联网的多人游戏服务器&#xff0c;将游戏服务器运行在云平台上&#xff0c;而不是在本地计算机中&#xff0c;这使用户不需要考虑自身电脑的性能和网络稳定性&#xff0c;只需要通过网络连接到云端服务器&#xff0c;就可以享受到顺畅的游戏体…...

shell脚本实现远程重启多个服务器

直接deepseek帮写脚本 remoteReboot.sh #!/bin/bash # 配置文件路径&#xff08;格式&#xff1a;每行一个服务器地址&#xff09; SERVER_FILE"servers.list" # 读取服务器列表 mapfile -t SERVERS < "$SERVER_FILE" for server in "${SERVER…...

怎样快速变换 json 串里的多层集合

有一个 2 层的 json 串&#xff0c;下层是多个动态的 key-value&#xff0c;不含集合 / 数组类型。 {"Games": {"key1": "value1", "key2": value2,"key3":value3}} 现在要把下层变换成多层的集合。 {"Games":…...

FreeCAD傻瓜教程-涡轮蜗杆的快速绘制FCGear工作台的使用方法

起因&#xff1a;涡轮蜗轴的组合&#xff0c;是一种比较简单且高效的传动结构。可以实现减速、加速、转动角度的放大、缩小等应用。 如何绘制呢&#xff1f;我搜索了不少教程&#xff0c;看起来都挺复杂的&#xff0c;对于小白来说有点像天书。这里介绍和记录一下利用FreeCAD 的…...

【论文阅读】HunyuanVideo: A Systematic Framework For Large Video Generative Models

HunyuanVideo: A Systematic Framework For Large Video Generative Models 原文摘要 研究背景与问题 视频生成的变革性影响&#xff1a;近期视频生成技术的进步深刻改变了个人生活与行业应用。 闭源模型的垄断&#xff1a;主流视频生成模型&#xff08;如Runway Gen-3、Luma …...

Search After+PIT 解决ES深度分页问题

1.深分页和search after 原理 深分页 (from/size)search_after数据定位全局排序后跳过前 N 条基于上一页最后一条的排序值定位排序开销每次请求重新全局排序 (O(N))仅首次全局排序&#xff0c;后续游标跳转 (O(1))内存消耗堆内存存储完整结果集 (高风险OOM)无堆内存累积 (安全…...

c语法高阶—(联合体,枚举,位域,编译器,宏定义,条件编译,条件编译,头文件)

目录 一 联合体&#xff08;重要&#xff09; 特性 总结 二 枚举&#xff08;重要&#xff09; 特性 总结&#xff1a; 三 位域&#xff08;了解&#xff09; 定义 特性 使用场景 优缺点分析表 位域的特点和使用方法 总结&#xff1a; 四 编译器&#xff08;linux…...

SQL Server To Paimon Demo by Flink standalone cluster mode

需求&#xff1a;使用 Flink CDC 测试 SQL Server 连接 Paimon 操作&#xff1a;启动 Flink standalone cluster 后&#xff0c;接着启动 Flink SQL Client&#xff0c;则通过 Flink SQL Client 提交 insert & select job 到该 8081 cluster Flink SQL Client 执行案例 -…...

常用设计模式在 Spring Boot 项目中的实战案例

引言​ 在当今的软件开发领域&#xff0c;Spring Boot 以其高效、便捷的特性成为构建 Java 应用程序的热门框架。而设计模式作为软件开发中的宝贵经验总结&#xff0c;能够显著提升代码的可维护性、可扩展性和可复用性。本文将深入探讨几种常用设计模式在 Spring Boot 项目中的…...

4、反应釜压力监控系统 - /自动化与控制组件/reaction-vessel-monitor

76个工业组件库示例汇总 反应釜压力监控组件 这是一个用于反应釜压力监控的自定义组件&#xff0c;专为化工厂反应釜压力监控设计。采用苹果工业风格界面&#xff0c;简洁优雅&#xff0c;功能实用&#xff0c;易于使用。 功能特点 实时压力可视化&#xff1a;直观展示反应…...

五、Hadoop集群部署:从零搭建三节点Hadoop环境(保姆级教程)

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月7日 专栏&#xff1a;Hadoop教程 前言&#xff1a; 想玩转大数据&#xff0c;Hadoop集群是绕不开的一道坎。很多小伙伴一看到集群部署就头大&#xff0c;各种配置、各种坑。别慌&#xff01;这篇教程就是你的“救生圈”。 …...

详细剖析传输层协议(TCP和UDP)

详细讲解传输层的网络协议&#xff0c;为什么TCP是可靠连接协议&#xff0c;凭什么能做到不丢包&#xff0c;有哪些机制保证可靠呢&#xff1f; TCP/UDP UDPTCP**三次握手和四次挥手****滑动窗口****拥塞控制**&#xff08;socket套接字&#xff09;**listen的第二个参数** UD…...

ZYNQ移植FreeRTOS与OpenAMP双核开发实践指南

ZYNQ系列芯片凭借其“ARM处理器(PS)+ FPGA(PL)”的异构架构,在嵌入式系统中被广泛应用于高性能计算与实时控制场景。然而,如何高效利用其双核资源并实现实时操作系统(如FreeRTOS)的移植与双核通信,是开发者面临的关键挑战。本文将深入探讨FreeRTOS移植、双核固化启动以…...

VUE+ElementUI 使用el-input类型type=“number” 时,取消右边的上下箭头

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在项目中有时候需要输入框的type“number”&#xff0c;这个时候&#xff0c;输入框的右边就会出现两个按钮&#xff0c;这两个按钮可以递增/递减&#xff0c;但是这样输入框看上去就不太美观&#x…...

RabbitMQ高级特性

1.消息的可靠投递 在使用 RabbitMQ 的时候&#xff0c;作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。 1.confirm 确认模式 2.return 退回模式 rabbitmq 整个消息投递的路径为&#xff1a; producer…...

在Python中调用C/C++函数并与MPI集成

在Python中调用C/C函数并与MPI集成 要在Python环境中调用C/C函数并让Python和C/C端都能使用MPI进行通信&#xff0c;有几种方法可以实现。下面我将介绍几种常见的方法。 方法一&#xff1a;使用mpi4py C/C MPI扩展 1. 准备工作 首先确保你已安装: MPI实现 (如OpenMPI或MP…...

软件架构评估方法全面解析

介绍 在软件开发过程中&#xff0c;架构设计的好坏直接影响系统的可维护性、可扩展性和性能。因此&#xff0c;软件架构评估&#xff08;Software Architecture Evaluation&#xff09;成为确保架构质量的关键步骤。本文将介绍几种主流的架构评估方法&#xff0c;包括ATAM、SA…...

场景可视化与数据编辑器:构建数据应用情境​

场景可视化是将数据与特定的应用场景相结合&#xff0c;借助数据编辑器对数据进行灵活处理和调整&#xff0c;通过模拟和展示真实场景&#xff0c;使企业能够更直观地理解数据在实际业务中的应用和影响&#xff0c;为企业的决策和运营提供有力支持。它能够将抽象的数据转化为具…...

MATLAB导出和导入Excel文件表格数据并处理

20250507 1.MATLAB使用table函数和writetable函数将数据导出Excel表格文件 我们以高斯函数为例子&#xff0c;高斯函数在数学和工程领域有着广泛的应用&#xff0c;它的一般形式为&#xff1a; 其中是均值&#xff0c;决定了函数的中心位置&#xff1b; 是标准差&#xff0c;决…...

2025年渗透测试面试题总结-渗透岗位全职工作面试(附回答)(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、通用基础类问题 1. 自我介绍 2. 职业动机与规划 3. 加班/出差接受度 二、安全技术类问题 1. 漏…...

【django.db.utils.OperationalError: unable to open database file】

解决platform.sh 环境下&#xff0c;无法打开数据库问题 场景 在platform.sh 执行python manage.py createsuperuser是提示 django.db.utils.OperationalError: unable to open database file 错误 原因 由于settings.py文件中 本地数据库配置在线上配置后&#xff0c;导致…...

【人工智能】解锁AI潜能:LM Studio多模型并行运行DeepSeek与开源大模型的实践指南

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大语言模型(LLM)的快速发展,LM Studio作为一款本地化部署工具,以其简单易用的图形化界面和强大的模型管理能力受到广泛关注。本文深…...

集群免密登录

免密登录原理 核心步骤 在hadoop100上 生成密钥对。把hadoop100的公钥发到hadoop101上。在hadoop100上登录hadoop101&#xff0c;验证效果 具体操作 登录 hadoop100。使用finalshell连接。在hadoop100上&#xff0c;运行命令&#xff1a;ssh-keygen -t rsa。然后根据提示连续敲…...

【C/C++】errno/strerror 和 GetLastError()/FormatMessage 的区别

strerror 和 errno 详解 printf("Error: %s\n", strerror(errno));这行代码用于在 C 语言中输出系统错误信息&#xff0c;但它与 Windows 的 GetLastError() 有重要区别。下面我将详细解释每个部分及其工作原理。 1. 组件解析 errno 定义&#xff1a;errno 是一个…...

ASP.NET MVC4 技术单选及多选题目汇编

一、单选题&#xff08;共50题&#xff0c;每题2分&#xff09; 1、ASP.NET MVC4 的核心架构模式是什么&#xff1f; A. MVP B. MVVM C. MVC D.三层架构 答案&#xff1a;C 2、在 MVC4 中&#xff0c;默认的路由配置文件名是&#xff1f; A. Global.asax B. RouteConfig.cs C.…...

趣味编程:梦幻万花筒

目录 1.效果展示 2.源码展示 3.代码逻辑详解 3.1 头文件与宏定义 3.2 HSV函数转RGB颜色函数 3.3 主函数 初始化部分 循环部分 线条绘制部分 刷新和延时部分 结束部分 4.小结 本篇博客主要介绍趣味编程用C语言实现万花筒小程序。 1.效果展示 2.源码展示 #define…...

使用 Selenium 截图功能,截不到原生 JavaScript 弹窗

本篇内容源自ai注意甄别 Selenium WebDriver 的标准截图 (getScreeenshotAs) 捕获的是浏览器渲染的 DOM 内容&#xff0c;而 JavaScript 的 alert()、confirm()、prompt() 这类弹窗是浏览器级别的原生 UI 元素&#xff0c;它们不属于页面的 DOM 结构。 为什么会这样&#xff…...

dubbo-token验证

服务提供者过滤器 import java.util.Map; import java.util.Objects;/*** title ProviderTokenFilter* description 服务提供者 token 验证* author zzw* version 1.0.0* create 2025/5/7 22:17**/ Activate(group CommonConstants.PROVIDER) public class ProviderTokenFilt…...

C++入门之认识整型

目录 一、变量 1.导入 2.变量 2.1 变量的作用 2.2 变量的定义方式 2.3 变量的“规矩” 二、数据类型 1.概念 2.int整型 三、C的常见运算 四、输入操作 4.1 cin 4.2 try 1 try 4.2.1 cin>> 4.2.2 定义的整数类型&#xff0c;输入字母会怎么样&#xff1f; …...

【数据结构入门训练DAY-28】蓝桥杯算法提高VIP-产生数

文章目录 前言一、题目二、解题思路结语 前言 本次训练内容 训练高精度乘法。训练解题思维。 一、题目 给出一个整数 n 和 k 个变换规则。规则&#xff1a;一位数可变换成另一个一位数&#xff1a;规则的右部不能为零。例如&#xff1a;n234。有规则&#xff08;k&…...

学习笔记:黑马程序员JavaWeb开发教程(2025.3.29)

11.5 案例-文件上传-阿里云OSS-入门 出现报错&#xff1a;Process exited with an error: 1 (Exit value: 1)&#xff0c;点击exec那一行&#xff0c;出现错误原因&#xff1a;Command execution failed. 在CSDN上找到了解决方法&#xff1a; 之后出现新的报错&#xff1a;Caug…...

大语言模型中的“温度”参数到底是什么?如何正确设置?

近年来&#xff0c;市面上涌现了大量调用大模型的工具&#xff0c;如 Dify、Cherry Studio 等开源或自研平台&#xff0c;几乎都提供了 “温度”&#xff08;Temperature&#xff09; 选项。然而&#xff0c;很多人在使用时并不清楚该如何选择合适的温度值。 今天&#xff0c;…...

【C++】C++中的类型转换

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a; C学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大…...

Go语言基础学习详细笔记

文章目录 初步了解Go语言Go语言诞生的主要问题和目标Go语言应用典型代表Go语言开发环境搭建经典HelloWorld 基本程序结构编写学习变量常量数据类型运算符 条件语句if语句switch 语句 跳转语句常用集合和字符串数组切片Map实现Set**字符串** 函数**基本使用用例验证** 面向对象编…...

初始图形学(7)

上一章完成了相机类的实现&#xff0c;对之前所学的内容进行了封装与整理&#xff0c;现在要学习新的内容。 抗锯齿 我们放大之前渲染的图片&#xff0c;往往会发现我们渲染的图像边缘有尖锐的"阶梯"性质。这种阶梯状被称为"锯齿"。当真实的相机拍照时&a…...

Linux 安装交叉编译器后丢失 `<asm/errno.h>` 的问题及解决方案

前言 在 Linux (Ubuntu等)环境下安装某些软件或开发环境时,我们可能会意外地引入交叉编译工具链,尤其是用于 ARM 架构的交叉编译器,比如 gcc-arm-linux-gnueabi 等。而这种行为会修改系统原有的开发环境,甚至导致无法编译原生程序。本文记录一次在 Ubuntu 18.04 上编译 …...

无人机上的热成像相机可以单独使用吗?

想知道无人机上的热成像相机是否可以单独使用&#xff0c;这需要从多个方面来分析。首先&#xff0c;得理解热成像相机的工作原理和依赖条件。热成像本身需要传感器和处理器来捕捉和处理红外辐射&#xff0c;所以无人机是否必须作为载体呢&#xff1f; 无人机上的热成像相机是否…...

go基于redis+jwt进行用户认证和权限控制

go基于redisjwt进行用户认证和权限控制&#xff1a; 基于 jwt 实现用户认证 基于 redis 记录用户的角色和权限 效果 实现 用户认证 和 权限控制 核心实现 下面的例子&#xff1a;有三个用户&#xff0c;分别为三个角色&#xff1a;admin、user、manager 路由&#xff1a; …...

深入理解Java三大特性:封装、继承和多态

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...