C++中线程安全的对多个锁同时加锁
C++中线程安全的对多个锁同时加锁
- C++中线程安全的对两个锁同时加锁
C++中线程安全的对两个锁同时加锁
参考文档:https://llfc.club/articlepage?id=2UVOC0CihIdfguQFmv220vs5hAG
如果我们现在有一个需要互斥访问的变量 big_object
,它的定义如下:
// 假如这个object是一个非常大的数据结构
class big_object {
public:big_object(int data) :_data(data) {}//拷贝构造big_object(const big_object& b2) :_data(b2._data) {_data = b2._data;}//移动构造big_object(big_object&& b2) :_data(std::move(b2._data)) {}//重载输出运算符friend std::ostream& operator << (std::ostream& os, const big_object& big_obj) {os << big_obj._data;return os;}//重载赋值运算符big_object& operator = (const big_object& b2) {if (this == &b2) {return *this;}_data = b2._data;return *this;}//交换数据friend void swap(big_object& b1, big_object& b2) {big_object temp = std::move(b1);b1 = std::move(b2);b2 = std::move(temp);}
private:// 这里使用随便一个变量用于表示其成员int _data;
};
由于这个是需要互斥访问的,所以每一个对象都需要有一个锁来确保线程安全的访问。所以定义一个big_object_mgr
来管理这个类。
// 现在使用一个线程安全的类对这个超大类做管理
class big_object_mgr {
public:big_object_mgr(int data = 0): _obj(data) {}void printinfo() {std::cout << "current obj data is " << _obj << std::endl;}friend void danger_swap(big_object_mgr& obj_1, big_object_mgr& obj_2);friend void safe_swap(big_object_mgr& obj_1, big_object_mgr& obj_2);friend void safe_swap_scope(big_object_mgr& obj_1, big_object_mgr& obj_2);private:std::mutex _mutex;big_object _obj;
};
我们以交换这两个big_object_mgr
对象为例,来说明一下如果线程安全的实现交换。
首先来看一下实现的,线程不安全的交换逻辑:
void danger_swap(big_object_mgr &obj_1, big_object_mgr &obj_2) {std::cout << "danger swap start" << std::endl;// 如果这两个对象是同一个对象,则直接返回if (&obj_1 == &obj_2) {return;}std::lock_guard<std::mutex> lock_guard1(obj_1._mutex);// 这个延时1s表示:用于演示两个锁加锁之间发生了线程运行交换std::this_thread::sleep_for(std::chrono::seconds(1));std::lock_guard<std::mutex> lock_guard2(obj_2._mutex);std::swap(obj_1._obj, obj_2._obj);std::cout << "danger swap end" << std::endl;
}
这个代码第一眼看上去是没有问题的,但是如果仔细分析一下,就可以知道有以下的问题:由于lock_guard1与2是非同时加锁的,所以可能会出现当lock_guard1加锁后,发生了线程的调度,此时会有另一个线程对lock_guard2进行了加锁,这样就会有可能发生了死锁。
实验代码如下:
void test_danger_swap() {big_object_mgr objm1(5);big_object_mgr objm2(100);std::thread t1(danger_swap, std::ref(objm1), std::ref(objm2));std::thread t2(danger_swap, std::ref(objm2), std::ref(objm1));t1.join();t2.join();objm1.printinfo();objm2.printinfo();
}
这里为了可以 100% 的产生死锁,我们通过在给lock_guard1
加锁成功后,延迟1秒再来加锁lock_guard2
。
以上就可以确定出问题:由于需要使用两个锁,但是当这两个锁没有同时加锁时,就会导致线程不安全。为了解决这个问题,我们可以使用std::lock()
实现对两个锁的同时加锁。现在来看safe_swap
代码的实现:
void safe_swap(big_object_mgr& obj_1, big_object_mgr& obj_2) {std::cout << "safe_swap start" << std::endl;if (&obj_1 == &obj_2) {return;}// 从上述的代码中可以看到,死锁的过程是在给两个锁分别加锁的过程中发生的// 所以只需要给这两个锁同时加锁就可以解决这个问题std::lock(obj_1._mutex, obj_2._mutex);// 如果想使用lock_guard来管理这个锁的释放,则可以使用领养锁来管理std::lock_guard<std::mutex> lock_guard1(obj_1._mutex, std::adopt_lock);// 这个延时1s表示:用于演示两个锁加锁之间发生了线程运行交换std::this_thread::sleep_for(std::chrono::seconds(1));std::lock_guard<std::mutex> lock_guard2(obj_2._mutex, std::adopt_lock);std::swap(obj_1._obj, obj_2._obj);std::cout << "safe_swap end" << std::endl;
}
由于std::lock_guard
会默认给传入的锁上锁,而我们使用std::lock
以后,就已经给锁上好锁了,所以就无法直接通过std::lock_guard
来对这个锁做管理。此时就可以通过领养锁std::adopt_lock
来实现对已经上过锁的锁的管理。此时,std::lock_guard
就只负责std::mutex
的释放,而不负责上锁。
这个的测试代码如下,可以看到,代码是可以正确的运行的:
void test_safe_swap() {big_object_mgr objm1(5);big_object_mgr objm2(100);std::thread t1(safe_swap, std::ref(objm1), std::ref(objm2));std::thread t2(safe_swap, std::ref(objm2), std::ref(objm1));t1.join();t2.join();objm1.printinfo();objm2.printinfo();
}
现在已经解决了同时上锁的问题,但是这样写代码又过于麻烦了,有没有更简单的办法呢?有的兄弟,有的。c++17中引入了一个std::scoped_lock
,可以使用这个锁来实现对两个锁的同时上锁,使用方式如下:
void safe_swap_scope(big_object_mgr& obj_1, big_object_mgr& obj_2) {std::cout << "safe_swap_scope start" << std::endl;if (&obj_1 == &obj_2) {return;}// 上述的方式还是太麻烦了,在c++17中引入了std::scoped_lock,可以同时对两个锁上锁,以及解锁std::scoped_lock guard(obj_1._mutex, obj_2._mutex);std::swap(obj_1._obj, obj_2._obj);std::cout << "safe_swap_scope end" << std::endl;
}
测试代码如下:
void test_safe_swap_scope() {big_object_mgr objm1(5);big_object_mgr objm2(100);std::thread t1(safe_swap_scope, std::ref(objm1), std::ref(objm2));std::thread t2(safe_swap_scope, std::ref(objm2), std::ref(objm1));t1.join();t2.join();objm1.printinfo();objm2.printinfo();
}
由于在开发中很难避免一个函数内同时加多个锁的情况,所以需要避免循环加锁。而我们可以使用层级锁来解决这个问题。
层级锁的实现如下:
// 层级锁
// 为了避免循环加锁,可以使用层级锁来完成加锁
// 如果不按顺序加锁,则会抛出异常
class hierarchical_mutex {
public:explicit hierarchical_mutex(unsigned long value):_hierarchy_value(value), _previous_hierarchy_value(0){};hierarchical_mutex(const hierarchical_mutex&) = delete;hierarchical_mutex& operator = (const hierarchical_mutex&) = delete;void lock() {check_for_hierarchy_violation();_internal_mutex.lock();update_hierarchy_violation();}void unlock() {// 如果解锁的顺序不对,则抛出异常if (_this_thread_hierarchy_value != _hierarchy_value) {throw std::logic_error("hierarchical_mutex unlock unexpectedly");}_this_thread_hierarchy_value = _previous_hierarchy_value;_internal_mutex.unlock();}bool try_lock() {check_for_hierarchy_violation();if (!_internal_mutex.try_lock()) {return false;}update_hierarchy_violation();return true;}private:std::mutex _internal_mutex;// 当前的层级值unsigned long const _hierarchy_value;// 上一级层级的值unsigned long _previous_hierarchy_value;// 本线程记录的层级值static thread_local unsigned long _this_thread_hierarchy_value;// 检测加锁是不是合理的void check_for_hierarchy_violation() {if (_this_thread_hierarchy_value <= _hierarchy_value) {throw std::logic_error("hierarchy violation");}}void update_hierarchy_violation() {_previous_hierarchy_value = _this_thread_hierarchy_value;_this_thread_hierarchy_value = _hierarchy_value;}};thread_local unsigned long hierarchical_mutex::_this_thread_hierarchy_value(ULONG_MAX);
层级锁的核心思路是通过**给每个锁分配一个层级(hierarchy level),并强制线程按照层级从高到低(数值从大到小)的顺序来获取锁,从而避免死锁。**如果加锁的顺序不正确,则会抛出异常,这会强迫程序员检查代码逻辑。
测试代码如下:
void test_hierarchy_lock() {hierarchical_mutex hmtx1(1000);hierarchical_mutex hmtx2(100);std::thread t1([&hmtx1, &hmtx2]() {hmtx1.lock();hmtx2.lock();hmtx2.unlock();hmtx1.unlock();});std::thread t2([&hmtx1, &hmtx2]() {hmtx2.lock();hmtx1.lock();hmtx1.unlock();hmtx2.unlock();});t1.join();t2.join();
}
相关文章:
C++中线程安全的对多个锁同时加锁
C中线程安全的对多个锁同时加锁 C中线程安全的对两个锁同时加锁 C中线程安全的对两个锁同时加锁 参考文档:https://llfc.club/articlepage?id2UVOC0CihIdfguQFmv220vs5hAG 如果我们现在有一个需要互斥访问的变量 big_object,它的定义如下: …...
子串简写(JAVA)一维前缀和, 蓝桥杯
这个题用前缀和,开两个数组,一个存前n个字符数据的c1的数字个数,另一个前n个字符c2的数字个数,然后遍历一次加起来,有一个测试点没过去,把那个存最后数的换成long,应该是这题数据范围给的不对&a…...
数据库故障排查全攻略:从实战案例到体系化解决方案
一、引言:数据库故障为何是技术人必须攻克的 "心腹大患" 在数字化时代,数据库作为企业核心数据资产的载体,其稳定性直接决定业务连续性。据 Gartner 统计,企业每小时数据库 downtime 平均损失高达 56 万美元࿰…...
vllm笔记
目录 vllm简介vllm解决了哪些问题?1. **瓶颈:KV 缓存内存管理低效**2. **瓶颈:并行采样和束搜索中的内存冗余**3. **瓶颈:批处理请求中的内存碎片化** 快速开始安装vllm开始使用离线推理启动 vLLM 服务器 支持的模型文本语言模型生…...
“AI+城市治理”智能化解决方案
目录 一、建设背景 二、需求分析 三、系统设计 四、系统功能 五、应用场景 六、方案优势 七、客户价值 八、典型案例 一、建设背景 当前我国城市化率已突破65%,传统治理模式面临前所未有的挑战。一方面,城市规模扩大带来治理复杂度呈指数级增长,全国城市管理案件年…...
《医疗AI的透明革命:破解黑箱困境与算法偏见的治理之路》
医疗AI透明度困境 黑箱问题对医生和患者信任的影响:在医疗领域,AI模型往往表现为难以理解的“黑箱”,这会直接影响医生和患者对其诊断建议的信任度 。医生如果无法理解AI给出诊断的依据,就难以判断模型是否存在偏见或错误&#x…...
【论文阅读】Efficient and secure federated learning against backdoor attacks
Efficient and secure federated learning against backdoor attacks -- 高效且安全的可抵御后门攻击的联邦学习 论文来源问题背景TLDR系统及威胁模型实体威胁模型 方法展开服务器初始化本地更新本地压缩高斯噪声与自适应扰动聚合与解压缩总体算法 总结优点缺点 论文来源 名称…...
21、DeepSeekMath论文笔记(GRPO)
DeepSeekMath论文笔记 0、研究背景与目标1、GRPO结构GRPO结构PPO知识点**1. PPO的网络模型结构****2. GAE(广义优势估计)原理****1. 优势函数的定义**2.GAE(广义优势估计) 2、关键技术与方法3、核心实验结果4、结论与未来方向关键…...
深入解析:如何基于开源p-net快速开发Profinet从站服务
一、Profinet协议与软协议栈技术解析 1.1 工业通信的"高速公路" Profinet作为工业以太网协议三巨头之一,采用IEEE 802.3标准实现实时通信,具有: 实时分级:支持RT(实时)和IRT(等时实时)通信模式拓扑灵活:支持星型、树型、环型等多种网络结构对象模型:基于…...
腾讯多模态定制化视频生成框架:HunyuanCustom
HunyuanCustom 速读 一、引言 HunyuanCustom 是由腾讯团队提出的一款多模态定制化视频生成框架。该框架旨在解决现有视频生成方法在身份一致性(identity consistency)和输入模态有限性方面的不足。通过支持图像、音频、视频和文本等多种条件输入,HunyuanCustom 能…...
警惕C#版本差异多线程中的foreach陷阱
警惕C#版本差异多线程中的foreach陷阱 同样的代码,不同的结果闭包捕获的“时间差”问题绕过闭包陷阱的三种方法Lambda立即捕获(代码简洁)显式传递参数(兼容性最佳)使用Parallel.ForEach(官方推荐)注意事项:版本兼容性指南警惕多线程中的foreach陷阱:C#版本差异引发的…...
2024年AI发展趋势全面解析:从多模态到AGI的突破
2024年AI发展五大核心趋势 1. 多模态AI的爆发式增长 GPT-4V、Gemini等模型实现文本/图像/视频的跨模态理解应用场景扩展至智能客服、内容创作、工业质检等领域 2. 小型化与边缘AI的崛起 手机端LLM(如Phi-2)实现本地化部署隐私保护与实时响应的双重优…...
高精度之加减乘除之多解总结(加与减篇)
开篇总述:精度计算的教学比较杂乱,无系统的学习,且存在同法多线的方式进行同一种运算,所以我写此篇的目的只是为了直指本质,不走教科书方式,步骤冗杂。 一,加法 我在此讲两种方法: …...
Arduino 开源按键库大合集(单击/双击/长按实现)
2025.5.10 22:25更新:增加了Button2 2025.5.10 13:13更新:增加了superButton 虽然Arduino自带按键中断attachInterrupt(button1.PIN, isr, FALLING);,但是要是要实现去抖,双击检测,长按检测等等就略微麻烦些࿰…...
相机Camera日志分析之八:高通Camx HAL架构opencamera三级日志详解及关键字
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:相机Camera日志分析之七:高通Camx HAL架构opencamera二级日志详解及关键字 这一篇我们开始讲: 相机Camera日志分析之八:高通Camx HAL架构opencamera三级日志详解及关键字 目录 【关注我,后续持续…...
Java零组件实现配置热更新
在某些场景下,我们需要实现配置的热更新,但是又要实现软件即插即用的需求,这就使我们不能引入过多复杂的插件,而nacos等配置中心在分布式业务场景下对配置的管理起着很重要作用,为此需要想一些办法去代替它们而完成同样…...
Kotlin高阶函数多态场景条件判断与子逻辑
Kotlin高阶函数多态场景条件判断与子逻辑 fun main() {var somefun: (Int, Float) -> Longval a 4val b 5fsomefun multi()//if 某条件println(somefun.invoke(a, b))//if 某条件somefun add()println(somefun.invoke(a, b)) }fun multi(): (Int, Float) -> Long {re…...
Ethercat转Profinet网关如何用“协议翻译术“打通自动化产线任督二脉
Ethercat转Profinet网关如何用"协议翻译术"打通自动化产线任督二脉 将遗留的Profinet设备(如传感器)接入现代EtherCAT主站(如Codesys控制器)避免全面更换硬件。 作为一名电气工程师,我最近面临的一个挑战&a…...
每日算法刷题Day1 5.9:leetcode数组3道题,用时1h
1.LC寻找数组的中心索引(简单) 数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台 思想: 计算总和和左侧和,要让左侧和等于右侧和,即左侧和总和-左侧和-当前数字 代码 c代码: class Solution { public:i…...
MySQL的视图
一、MySQL视图的介绍和作用 MySQL视图,加油兄弟们,孰能生巧,完整代码在最后!!! 视图是一个虚拟的表,并不是真是存在的,视图其实并没有真实的数据,他只是根据一个sql语句…...
旅游推荐数据分析可视化系统算法
旅游推荐数据分析可视化系统算法 本文档详细介绍了旅游推荐数据分析可视化系统中使用的各种算法,包括推荐算法、数据分析算法和可视化算法。 目录 推荐算法 基于用户的协同过滤推荐基于浏览历史的推荐主题推荐算法 亲子游推荐算法文化游推荐算法自然风光推荐算法…...
Pandas:数据处理与分析
目录 一、Pandas 简介 二、Pandas 的安装与导入 三、Pandas 的核心数据结构 (一)Series (二)DataFrame 四、Pandas 数据读取与写入 (一)读取数据 (二)写入数据 五、数据清洗…...
非阻塞式IO-Java NIO
一、NIO简介 Java NIO是Java1.4引入的一种新的IO API,它提供了非阻塞式IO,选择器、通道、缓冲区等新的概念和机制。相比传统的IO,多出的N不单纯是新的,更表现在Non-blocking非阻塞,NIO具有更高的并发性、可扩展性以及…...
tryhackme——Enumerating Active Directory
文章目录 一、凭据注入1.1 RUNAS1.2 SYSVOL1.3 IP和主机名 二、通过Microsoft Management Console枚举AD三、通过命令行net命令枚举四、通过powershell枚举 一、凭据注入 1.1 RUNAS 当获得AD凭证<用户名>:<密码>但无法登录域内机器时,runas.exe可帮助…...
(二)Linux下基本指令 2
【知识预告】 16. date 指令 17. cal 指令 18. find 指令 19. which指令 20. whereis 指令 21. alias 指令 22. grep 指令 23. zip/unzip 指令 24. tar 指令 25. bc 指令 26. uname ‒r 指令 27. 重要的⼏个热键 28. 关机 16 date 指令 指定格式显⽰时间:date %Y-…...
[ctfshow web入门] web70
信息收集 使用cinclude("php://filter/convert.base64-encode/resourceindex.php");读取的index.php error_reporting和ini_set被禁用了,不必管他 error_reporting(0); ini_set(display_errors, 0); // 你们在炫技吗? if(isset($_POST[c])){…...
第三章 Freertos智能小车遥控控制
本文基于小车APP,通过与蓝牙模块进行连接,发送特定信号给小车主控,实现对小车的模式切换、灯光控制、前进、后退、左右控制。目前还未加入电机控制,具体的电机控制效果还不能实现,但是可以进行模式切换与灯光控制。 …...
Spring 6.x 详解介绍
Spring 6.x 是 Spring Framework 的最新主版本,于2022年11月正式发布,标志着对 Java 17 和 Jakarta EE 9 的全面支持,同时引入了多项革新性特性,旨在优化性能、简化开发并拥抱现代技术趋势。 一、核心特性与架构调整 Java 17 与 J…...
阿里云OSS+CDN自动添加文章图片水印配置指南
文章目录 一、环境准备二、OSS水印样式配置三、CDN关键配置四、Handsome主题自动化配置五、水印效果验证六、常见问题排查 一、环境准备 资源清单 阿里云OSS Bucket(绑定自定义域名 static.example.com)阿里云CDN加速域名,回源为Bucket的域名…...
hot100-子串-JS
一、560.和为k的子串 560. 和为 K 的子数组 提示 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2…...
LeetCode 270:在二叉搜索树中寻找最接近的值(Swift 实战解析)
文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结 摘要 在日常开发中,我们经常需要在一组有序的数据中快速找到最接近某个目标值的元素。LeetCode 第 270 题“Closest Binary Search Tree Value”正是这样一个问题。本文将深入解析该…...
《操作系统真象还原》第十三章——编写硬盘驱动程序
文章目录 前言硬盘及分区表创建从盘及获取安装的磁盘数创建磁盘分区表硬盘分区表浅析 编写硬盘驱动程序硬盘初始化修改interrupt.c编写ide.h编写ide.c 实现thread_yield和idle线程修改thread.c 实现简单的休眠函数修改timer.c 完善硬盘驱动程序继续编写ide.c 获取硬盘信息&…...
DNS服务实验
该文章将介绍DNS服务的正向和反向解析实验、主从实验、转发服务器实验以及Web解析实验 正向解析实验:将域名解析为对应的IP地址 反向解析实验:将IP地址解析为对应的域名 主从实验:主服务器区域数据文件发送给从服务器,从服务器…...
SierraNet M1288网络损伤功能显著助力GPU互联网络的测试验证,包含包喷洒,LLR等复杂特性的验证测试
SierraNet M1288 以太网协议分析仪 产品概述 SierraNet M1288 是一款兼具高性价比与全面功能的以太网和光纤通道数据捕获及协议验证系统。它能够以全线路速率 100% 记录所有流量,并借助 InFusion™ 工具实现高级错误注入和流量破坏功能,为开发人员和协议…...
HunyuanCustom:文生视频框架论文速读
《HunyuanCustom: A Multimodal-Driven Architecture for Customized Video Generation》论文讲解 一、引言 本文提出了 HunyuanCustom,这是一个基于多模态驱动的定制化视频生成框架。该框架旨在解决现有视频生成模型在身份一致性(identity consistenc…...
HTTP、HTTPS、SSH区别以及如何使用ssh-keygen生成密钥对
HTTP、HTTPS、SSH区别以及如何使用ssh-keygen生成密钥对 HTTP (HyperText Transfer Protocol) 定义:应用层协议,用于通过Web传输数据(如网页、文件)默认端口:80机制:客户端发送Get请求,服务器…...
如何启动vue项目及vue语法组件化不同标签应对的作用说明
如何启动vue项目及vue语法组件化不同标签应对的作用说明 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是node.js和vue的使用。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】&…...
Ubuntu22.04安装显卡驱动/卸载显卡驱动
报错 今日输入nvidia-smi报错,在安装了535和550,包括560都没办法解决,但是又怕乱搞导致环境损坏,打算把显卡卸载然后重新安装系统默认推荐版本的显卡驱动 qinqin:~$ nvidia-smi Failed to initialize NVML: Driver/library version mismatch NVML library version: 560.35卸载…...
【桌面】【输入法】常见问题汇总
目录 一、麒麟桌面系统输入法概述 1、输入法介绍 2、输入法相关组件与服务 3、输入法调试相关命令 3.1、输入法诊断命令 3.2、输入法配置重新加载命令 3.3、启动fcitx输入法 3.4、查看输入法有哪些版本,并安装指定版本 3.5、重启输入法 3.6、查看fcitx进程…...
Web3 初学者学习路线图
目录 🌟 Web3 初学者学习路线图 🧩 第一步:搞懂 Web3 是什么 ✅ 学什么? 🔧 推荐工具: 🎥 推荐学习: 🛠️ 第二步:了解智能合约和 Solidity(核心技能) ✅ 学什么? 🔧 工具: 📘 推荐课程: 🌐 第三步:连接前端和区块链,创建简单 DApp ✅ 学…...
python打卡day21
常见的降维算法 知识点回顾: LDA线性判别PCA主成分分析t-sne降维 之前学了特征降维的两个思路,特征筛选(如树模型重要性、方差筛选)和特征组合(如SVD/PCA)。 现在引入特征降维的另一种分类:无/有…...
KNOWLEDGE-BASED SYSTEMS(KBS期刊)投稿经验分享
期刊介绍: KBS是计算机一区,CCF-c期刊,(只看大类分区,小类不用看,速度很快,桌拒比较多,能送审就机会很大!) 具体时间流程: 7月初投稿…...
vue使用rules实现表单校验——校验用户名和密码
编写校验规则 常规校验 const rules {username: [{ required: true, message: 请输入用户名, trigger: blur },{ min: 5, max: 16, message: 长度在 5 到 16 个字符, trigger: blur }],password: [{ required: true, message: 请输入密码, trigger: blur },{ min: 5, max: 1…...
[CANN] 安装软件依赖
环境 昊算平台910b NPUdocker容器 安装步骤 安装依赖-安装CANN(物理机场景)-软件安装-开发文档-昇腾社区 apt安装miniconda安装 Apt 首先进行换源,参考昇腾NPU容器内 apt 换源 Miniconda 安装miniconda mkdir -p ~/miniconda3 wget …...
代码随想录算法训练营第三十七天
LeetCode题目: 300. 最长递增子序列674. 最长连续递增序列718. 最长重复子数组2918. 数组的最小相等和(每日一题) 其他: 今日总结 往期打卡 300. 最长递增子序列 跳转: 300. 最长递增子序列 学习: 代码随想录公开讲解 问题: 给你一个整数数组 nums ,找到其中最长…...
Qt开发经验 --- 避坑指南(11)
文章目录 [toc]1 QtCreator同时运行多个程序2 刚安装的Qt编译报错cannot find -lGL: No such file or directory3 ubuntu下Qt无法输入中文4 Qt版本发行说明5 Qt6.6 VS2022报cdb.exe无法定位dbghelp.dll输入点6 Qt Creator13.0对msvc-qmake-jom.exe支持有问题7 银河麒麟系统中ud…...
vue 组件函数式调用实战:以身份验证弹窗为例
通常我们在 Vue 中使用组件,是像这样在模板中写标签: <MyComponent :prop"value" event"handleEvent" />而函数式调用,则是让我们像调用一个普通 JavaScript 函数一样来使用这个组件,例如:…...
青藏高原东北部祁连山地区250m分辨率多年冻土空间分带指数图(2023)
时间分辨率:10年 < x < 100年空间分辨率:100m - 1km共享方式:开放获取数据大小:24.38 MB数据时间范围:近50年来元数据更新时间:2023-10-08 数据集摘要 多年冻土目前正在经历大规模的退化,…...
[6-2] 定时器定时中断定时器外部时钟 江协科技学习笔记(41个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 V 30 31 32 33 34 35 36 37 38 39 40 41...
抖音视频去水印怎么操作
在抖音上保存或分享视频时,水印通常会自动添加。如果想去除水印,可以尝试以下方法,但请注意尊重原创作者的版权,仅限个人合理使用。 方法 1:使用第三方去水印工具(手机/电脑均可) 复制视频链接 …...