【C++】:C++11详解 —— 线程库
目录
线程库(thread)
线程对象的构造函数
构造函数的用法示例
参数传递的关键细节
构造函数的异常行为
线程对象的使用
互斥量库(mutex)
互斥量类型
锁管理类(RAII 封装)
条件变量(condition_variable)
wait()
notify_one() 与 notify_all()
代码实践
线程库(thread)
在C++11之前,涉及到多线程问题,都是和平台相关的,比如Windows 和 Linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行了支持,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。
线程对象的构造函数
C++11 中 std::thread
的构造函数是创建线程的核心接口,负责将可调用对象(如函数、Lambda 表达式、函数对象等)与参数绑定,并启动一个新线程执行。
构造函数的用法示例
// 基本语法
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
参数:
-
f
:可调用对象(函数、Lambda、成员函数指针等)。 -
args...
:传递给f
的参数列表。
语义:
-
参数
f
和args
按完美转发(std::forward
)的方式传递。 -
新线程在构造函数调用时立即启动。
-
如果线程无法创建(如资源不足),构造函数会抛出
std::system_error
异常。
普通函数
void print(int x, const std::string& s)
{std::cout << x << " " << s << std::endl;
}std::thread t(print, 42, "Hello"); // 启动线程执行 print(42, "Hello")
t.join();
Lambda 表达式
std::thread t([](int x) {std::cout << x << std::endl;
}, 42);
t.join();
成员函数
// 需要传递对象的指针或引用
class MyClass
{
public:void task(int x) { /* ... */ }
};MyClass obj;
std::thread t(&MyClass::task, &obj, 42); // 传递对象指针和参数
t.join();
函数对象(Functor)
struct Task
{void operator()(int x) { /* ... */ }
};Task task;
std::thread t(task, 42); // 传递函数对象实例
t.join();
参数传递的关键细节
1、按值传递 vs 按引用传递
-
默认按值传递:参数会被拷贝到线程的独立内存空间中。
-
按引用传递:需使用
std::ref
或std::cref
包装参数
void modify(int& x) { x = 42; }int value = 0;
std::thread t(modify, ref(value)); // 按引用传递
t.join();
std::cout << value; // 输出 42
2、移动语义
-
对于不可复制的对象(如
std::unique_ptr
),必须使用std::move
:
std::unique_ptr<int> ptr = std::make_unique<int>(42);
std::thread t([](std::unique_ptr<int> p)
{std::cout << *p << std::endl;
}, std::move(ptr)); // 转移所有权
t.join();
构造函数的异常行为
-
如果线程创建失败(如系统资源不足),构造函数抛出
std::system_error
。
try
{std::thread t(/* ... */);t.join();
}
catch (const std::system_error& e)
{std::cerr << "线程创建失败: " << e.what() << std::endl;
}
注意事项
1、线程的生命周期:
-
线程对象析构前必须调用
join()
或detach()
,否则程序调用std::terminate
。 -
推荐使用 RAII 管理线程:
class ThreadGuard
{std::thread& t;
public:explicit ThreadGuard(std::thread& t_) : t(t_) {}~ThreadGuard() {if (t.joinable()) {t.join();}}
};std::thread t(/* ... */);
ThreadGuard guard(t); // 确保线程安全退出
2、参数的生命周期:
-
确保线程中使用的参数在线程执行期间有效。例如,避免传递局部变量的引用:
void bad_example()
{int local = 42;std::thread t([](int& x) { x = 0; }, std::ref(local));t.detach(); // 线程可能访问已销毁的 local
}
- 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态。
-
构造时不提供函数则对象为空;提供函数则自动启动新线程执行,与原线程并发。
-
std::thread
不可拷贝,但支持移动语义(转移所有权,不影响线程运行)。
线程对象的使用
成员函数 | 功能描述 | 注意事项 |
---|---|---|
join() | 阻塞当前线程,等待目标线程完成执行。 | 若线程不可 join (已分离或空对象),抛出 std::system_error 。 |
detach() | 分离线程,使其独立运行(放弃对线程的控制)。 | 分离后无法再 join 或操作线程;若不可分离,抛出 std::system_error 。 |
joinable() | 检查线程是否可 join 或 detach 。 | 返回 true 的条件:线程已启动且未 join 或 detach 。 |
get_id() | 获取线程的唯一标识符(std::thread::id )。 | 若线程未关联或已分离,返回默认构造的 id (表示“无线程”)。 |
native_handle() | 获取底层平台相关的线程句柄(如 pthread_t 或 HANDLE )。 | 主要用于与平台特定 API 交互,非跨平台代码慎用。 |
swap() | 交换两个线程对象关联的线程。 | 高效交换所有权,不影响线程实际运行。 |
hardware_concurrency() (静态) | 返回当前系统支持的并发线程数(近似于逻辑 CPU 核心数)。 | 返回值可能为 0(若系统信息不可用),需谨慎处理。 |
void task()
{std::cout << "线程ID: " << std::this_thread::get_id() << std::endl;
}int main()
{std::thread t(task);if (t.joinable()) // 检查是否可操作{t.detach(); // 分离线程(或选择 t.join())}// 获取系统支持的并发线程数std::cout << "并发线程数: " << std::thread::hardware_concurrency() << std::endl;// 获取分离后的线程ID(无效)std::cout << "分离后的线程ID: " << t.get_id() << std::endl;return 0;
}
互斥量库(mutex)
用于保护共享数据,防止多个线程同时访问导致的 数据竞争(Data Race),确保线程安全。
互斥和原子性
- 在多线程情况下,如果这多个执行流都自顾自的对临界资源进行操作,那么此时就可能导致数据不一致的问题。(比如我们在抢票的时候,多个用户抢重复的票的时候,就会有导致强抢到重复的票)
- 解决该问题的方案就叫做互斥,互斥的作用就是,保证在任何时候有且只有一个执行流进入临界区对临界资源进行访问。
- 原子性指的是不可被分割的操作,该操作不会被任何调度机制打断,该操作只有两态,要么完成,要么未完成。
类型 | 描述 | 适用场景 |
---|---|---|
mutex | 基础互斥量,不可递归加锁。 | 简单场景,单次加锁。 |
recursive_mutex | 允许同一线程多次加锁(递归锁)。 | 需要递归调用的复杂逻辑。 |
timed_mutex | 支持超时功能的互斥量(try_lock_for /try_lock_until )。 | 需要限制等待时间的场景。 |
recursive_timed_mutex | 递归锁 + 超时功能。 | 递归调用且需超时控制的场景。 |
互斥量类型
互斥量(Mutex)是线程同步的基础工具,C++11 提供了四种互斥量类型:
1、mutex
-
基本特性:非递归锁,同一线程不可重复加锁。
-
适用场景:简单场景,仅需单次加锁保护共享资源。
-
核心操作:
-
lock()
:加锁,若锁已被其他线程持有则阻塞。 -
unlock()
:释放锁。 -
try_lock()
:尝试加锁,成功返回true
,否则返回false
(非阻塞)。
-
#include <mutex>
#include <thread>std::mutex mtx;
int shared_data = 0;void increment()
{mtx.lock();++shared_data;mtx.unlock();
}int main()
{std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();// 正确输出 shared_data = 2
}
2、recursive_mutex
-
特性:允许同一线程多次加锁(递归锁)。
-
适用场景:递归函数中需要重复访问共享资源。
-
注意:加锁次数必须与解锁次数匹配。
recursive_mutex rmtx;void recursive_func(int n)
{rmtx.lock();if (n > 0) {// 递归调用自身recursive_func(n - 1);}rmtx.unlock();
}
3、timed_mutex
-
特性:支持超时加锁(
try_lock_for
和try_lock_until
)。 -
适用场景:需要限制等待锁的时间,避免无限阻塞。
timed_mutex tmtx;void try_lock_task()
{if (tmtx.try_lock_for(std::chrono::milliseconds(100))) {// 成功获取锁tmtx.unlock();} else {// 超时未获取锁}
}
4、recursive_timed_mutex
-
特性:结合递归锁和超时功能。
-
适用场景:需要递归加锁且控制等待时间的场景。
锁管理类(RAII 封装)
为避免手动管理锁的释放,C++11 提供了基于 RAII 的锁管理类。
1、lock_guard
-
特性:构造时自动加锁,析构时自动解锁。
-
适用场景:简单的局部锁管理,无手动控制需求。
#include <mutex>
using namespace std;mutex mtx;
void safe_increment()
{std::lock_guard<std::mutex> lock(mtx);++shared_data; // 自动加锁/解锁
}
2、unique_lock
-
特性:
-
支持延迟加锁(
std::defer_lock
)。 -
允许手动加锁/解锁。
-
可移动(转移锁的所有权)。
-
与条件变量配合使用。
-
-
适用场景:需要灵活控制锁的获取与释放。
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void waiting_thread()
{std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; }); // 等待条件成立
}void notifying_thread()
{{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();
}
3、scoped_lock
(C++17)
-
特性:同时管理多个互斥量,避免死锁。
-
适用场景:需要同时锁定多个互斥量时。
std::mutex mtx1, mtx2;void safe_operation()
{std::scoped_lock lock(mtx1, mtx2); // 同时锁定 mtx1 和 mtx2// 安全操作共享数据
}
条件变量(condition_variable)
条件变量(std::condition_variable
)是 C++11 标准库中用于线程间同步的核心工具,常与互斥量(std::mutex
)配合使用,实现线程的阻塞等待和唤醒机制。
接口 | 功能 |
---|---|
void wait(std::unique_lock<std::mutex>& lock) | 阻塞当前线程,直到被唤醒(需手动检查条件)。 |
template <typename Predicate> void wait(lock, Predicate pred) | 阻塞线程,直到 pred 返回 true (自动检查条件,避免虚假唤醒)。 |
void notify_one() | 唤醒一个正在等待的线程(若有多个线程等待,随机选择一个)。 |
void notify_all() | 唤醒所有正在等待的线程。 |
wait()
wait()
:等待条件成立
基本用法:必须与 std::unique_lock
配合使用。
问题:存在虚假唤醒(线程可能未被通知就醒来),需手动检查条件。
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void waiting_thread()
{std::unique_lock<std::mutex> lock(mtx);cv.wait(lock); // 阻塞,直到被唤醒(需手动检查条件)if (ready) {// 条件成立后的操作}
}void notifying_thread()
{{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();
}
带谓词的
wait()
(推荐)
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void waiting_thread()
{std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; }); // 自动检查条件,避免虚假唤醒if (ready) {// 条件成立后的操作}
}void notifying_thread()
{{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();
}
等价于:
while (!ready)
{wait(lock);
}
notify_one()
与 notify_all()
notify_one()
:唤醒一个等待线程。notify_all()
:唤醒所有等待线程。
cv.notify_one(); // 适用于单生产者-单消费者场景
cv.notify_all(); // 适用于多消费者场景
代码实践
1、线程分工:
-
线程t1:负责打印奇数(1,3,5,...,99)。
-
线程t2:负责打印偶数(2,4,6,...,100)。
2、同步机制:
-
互斥锁
mutex
:确保同一时间只有一个线程访问共享资源(flag
和cout
)。 -
条件变量
condition_variable
:通过flag
的状态控制线程交替执行。
3、核心逻辑:
-
初始状态:
flag = true
,t1 先执行。 -
线程t1:等待
flag == true
,打印奇数后设置flag = false
,唤醒 t2。 -
线程t2:等待
flag == false
,打印偶数后设置flag = true
,唤醒 t1。
4、正确性验证:
-
每次操作在锁的保护下进行,避免数据竞争。
-
使用带谓词的
wait()
,防止虚假唤醒。 -
线程交替唤醒,最终均能正常退出循环。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>using namespace std;void print_number(bool is_odd, int max_num, mutex& mtx, condition_variable& cv, bool& flag)
{int start = is_odd ? 1 : 2;for (int i = start; i <= max_num; i += 2) {unique_lock<mutex> lock(mtx);cv.wait(lock, [&flag, is_odd] { return flag == is_odd; });cout << this_thread::get_id() << ": " << i << endl;flag = !is_odd;cv.notify_one();}
}int main()
{const int max_num = 100;mutex mtx;condition_variable cv;bool flag = true;thread t1(print_number, true, max_num, ref(mtx), ref(cv), ref(flag));thread t2(print_number, false, max_num, ref(mtx), ref(cv), ref(flag));t1.join();t2.join();return 0;
}
相关文章:
【C++】:C++11详解 —— 线程库
目录 线程库(thread) 线程对象的构造函数 构造函数的用法示例 参数传递的关键细节 构造函数的异常行为 线程对象的使用 互斥量库(mutex) 互斥量类型 锁管理类(RAII 封装) 条件变量(…...
招聘面试季--一文顿悟,Java中字节流和字符流的区别及使用场景上的差异
一、核心区别 特性字节流字符流数据单位以字节(8-bit)为单位处理数据(如0xA1)以字符(16-bit Unicode)为单位处理数据(如A, 你)基类InputStream / OutputSt…...
在 ARM 嵌入式 Linux 下使用 C/C++ 实现 MQTT
在 ARM 嵌入式 Linux 下使用 C/C 实现 MQTT 通信是一个常见的需求,尤其是在资源受限的环境中。以下是一个详细的教程,使用 Eclipse Paho C Client 库来实现 MQTT 客户端。 1. 安装 Eclipse Paho C Client 库 Eclipse Paho C Client 是一个轻量级的 MQTT…...
C++20 中 `constexpr` 的强大扩展:算法、工具与复数库的变革
文章目录 一、constexpr 在 <algorithm> 中的应用1. 编译时排序2. 编译时查找 二、constexpr 在 <utility> 中的应用1. 编译时交换2. 编译时条件交换 三、constexpr 在 <complex> 中的应用1. 编译时复数运算 四、总结 C20 对 constexpr 的增强是其最引人注目…...
C++ 介绍STL底层一些数据结构
c 标准模板库中,set和map的底层实现通常基于红黑树,然们都是平衡二叉搜索树(Balanceed Binary Serach Tree)的一种,这种结构保证了 插入,删除,查找的时间复杂度为O(log n)比普通二叉搜索树更高效。 set set<T>…...
算法2--两数相加
题目描述 解题思路 题目说的很详细了,也就是把每个数倒序写成链表进行输入,然后让你计算两个倒序数组的和,要保证跟预期的结果一样。 首先应该考虑的是两个数组的长度问题,对于链表的每一位进行加法运算,如果两个列表…...
Docker搭建Testlink教程
1.拉取镜像 打开终端输入命令: #拉取mariadb镜像 docker pull bitnami/mariadb #拉取testlink镜像 docker pull bitnami/testlink-archived 执行结果: 2.运行容器 打开终端输入命令: #创建容器网络 docker network create testlink #查…...
安卓7.0以上App抓包
安卓7.0以上App抓包 导出BurpSuite证书 设置本机IP的8080端口监听 证书转换 将这个der证书下载到kali上,并使用以下命令进行证书转换 openssl x509 -inform der -in cacert.der -out burp.pem openssl x509 -inform PEM -subject_hash_old -in burp.pem转换成功…...
CCBCISCN复盘
AWDP – ccfrum 自己搭了一下环境, 复现一下这道题目, 之前比赛的时候完全没想到这个漏洞要怎么打, 修也不知道要怎么修, 就仅仅是对用户名的账号和密码进行了一下过滤, 完全没起到作用, 唉, 实在太菜 如果想要尝试复现的话可以尝试拉取这个镜像, 我打完之后就直接把这个容器给…...
【C++】八大常见的设计模式的实现与实践指南
目录 创建型模式 单例模式工厂方法模式抽象工厂模式 结构型模式 适配器模式装饰者模式代理模式 行为型模式 观察者模式策略模式命令模式 高级主题 现代C特性影响模式性能对比典型应用案例 设计模式分类 一、创建型模式 1. 单例模式(Singleton) 现代…...
OpenEMMA: 基于多模态大语言模型的端到端开源自动驾驶框架
OpenEMMA: 基于多模态大语言模型的端到端开源自动驾驶框架 创新点 OpenEMMA 将前置摄像头图像和车辆历史文本状态作为输入。驾驶任务被构建为视觉问答(VQA)问题,利用思维链推理来指导模型生成关键物体的详细描述、行为洞察和元驾驶决策。这…...
kali,NTFS,用户管理,文件共享,本地安全策略,计算机基础
kali更新源 vim /etc/apt/sources.list 优质源 中科大Kali镜像源deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contribdeb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib阿里云Kali镜像源deb http://mirrors.aliyun.com…...
零基础上手Python数据分析 (7):Python 面向对象编程初步
写在前面 回顾一下,我们已经学习了 Python 的基本语法、数据类型、常用数据结构和文件操作、异常处理等。 到目前为止,我们主要采用的是 面向过程 (Procedural Programming) 的编程方式,即按照步骤一步一步地编写代码,解决问题。 这种方式对于简单的任务已经足够,但当程序…...
基于深度学习的皮肤癌智能检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
脚本一键式启动Nginx、Mysql、Redis
此脚本包含拉取镜像、数据卷挂载、容器启动三大部分,可一键式安装三大环境 新建一个depoy.sh文件在服务器上,然后复制以下内容。 给脚本文件添加执行权限 chmod x depoy.sh # 文件的当前目录下 如果需要修改数据库MYSQL密码和Reids密码 MYSQL_ROO…...
蓝桥杯备赛-DFS-有奖问答
问题描述 小蓝正在参与一个现场问答的节目。活动中一共有 3030 道题目, 每题只有答对和答错两种情况, 每答对一题得 1010 分,答错一题分数归零。 小蓝可以在任意时刻结束答题并获得目前分数对应的奖项,之后不能再答任何题目。最高奖项需要 100100 分, …...
[AI速读]CHISEL vs. SystemVerilog:用RISC-V核心对比两种硬件设计语言
在硬件设计领域,选择合适的语言对开发效率、维护成本和最终性能都至关重要。最近,一项研究对比了两种硬件描述语言——CHISEL(基于Scala的嵌入式语言)和传统的SystemVerilog,它们分别实现了同一款RISC-V核心(SweRV-EL2)。以下是关键发现和结论。 为什么选择CHISEL? CHI…...
PHP PSR(PHP Standards Recommendations)介绍
PHP PSR(PHP Standards Recommendations)是 PHP 社区制定的一系列标准化规范,旨在统一 PHP 代码的编写方式、接口设计和开发实践,以提高代码的可读性、可维护性和互操作性。以下是核心 PSR 标准的解读和具体使用方法: …...
字节跳动实习生主导开发强化学习算法,助力大语言模型性能突破
目录 禹棋赢的背景与成就 主要成就 DAPO算法的技术细节 算法优势 禹棋赢的研究历程 关键时间节点 字节跳动的“Top Seed人才计划” 计划特点 小编总结 在大模型时代,经验不再是唯一的衡量标准,好奇心、执行力和对新技术的敏锐洞察力成为推动技术…...
Java并发编程面试题:锁(17题)
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写
上一篇下一篇RNN(中集)待编写 代码详解 pytorch 官网主要有两个可调用的模块,分别是 nn.RNNCell 和 nn.RNN ,下面会进行详细讲解。 RNN 的同步多对多、多对一、一对多等等结构都是由这两个模块实现的,只需要将对输入…...
【python】OpenCV—Hand Landmarks Detection
文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、涉及到的库函数6、参考 更多有趣的代码示例,可参考【Programming】 1、功能描述 基于 opencv-python 和 mediapipe 实现手部关键点的检测(无法检测出手,不过可以根据关键点的信息外…...
C++和标准库速成(十)——类型别名、类型定义、类型推断和标准库简介
目录 1. 类型别名2. 类型定义(不建议)3. 类型推断3.1 auto3.1.1 auto&3.1.2 auto*3.1.3 拷贝列表初始化和直接列表初始化 3.2 decltype 4. 标准库简介参考 1. 类型别名 类型别名为现有的类型声明提供新名称。可以将类型别名视为用于为现有类型声明引入同义词而无须创建新类…...
Java JMX 未授权访问漏洞分析与修复指南
#作者:张桐瑞 文章目录 一、漏洞背景二、漏洞描述三、漏洞影响四、修复方案1. 禁用远程JMX访问:2. 配置JMX访问权限: 一、漏洞背景 Java管理扩展(Java Management Extensions,简称JMX)是Java平台的管理和…...
挂谷问题与挂谷猜想:从平面转针到高维拓扑
挂谷问题与挂谷猜想:从平面转针到高维拓扑 目录 挂谷问题的起源数学定义与基本性质研究进展挂谷集合与挂谷猜想王虹与Joshua Zahl的突破意义与影响 挂谷问题的起源 1917年,日本数学家挂谷宗一(かけや そういち Soichi Kakeya,1886-1947)提…...
区块链 智能合约安全 | 整型溢出漏洞
目录: 核心概念 溢出类型 上溢 原理 案例 下溢 原理 案例 练习 漏洞修复 使用 SafeMath 库(旧版本) 升级 Solidity 版本(≥0.8.0) 地址:zkanzz 整型溢出漏洞(Integer Overflow/Underflow Vulne…...
C# HTTP 文件上传、下载服务器
程序需要管理员权限,vs需要管理员打开 首次运行需要执行以下命令注册URL(管理员命令行) netsh advfirewall firewall add rule name"FileShare" dirin actionallow protocolTCP localport8000 ipconfig | findstr "IPv4&quo…...
IDEA导入jar包后提示无法解析jar包中的类,比如无法解析符号 ‘log4j‘
IDEA导入jar包后提示无法解析jar包中的类 问题描述解决方法 问题描述 IDEA导入jar包的Maven坐标后,使用jar中的类比如log4j,仍然提示比如无法解析符号 log4j。 解决方法 在添加了依赖和配置文件后,确保刷新你的IDE项目和任何缓存ÿ…...
C++前缀和
个人主页:[PingdiGuo_guo] 收录专栏:[C干货专栏] 大家好,今天我们来了解一下C的一个重要概念:前缀和 目录 1.什么是前缀和 2.前缀和的用法 1.前缀和的定义 2.预处理前缀和数组 3.查询区间和 4.数组中某个区间的和是否为特定…...
kafka压缩
最近有幸公司参与kafka消息压缩,背景是日志消息量比较大。kafka版本2.4.1 一、确认压缩算法 根据场景不同选择不同。如果是带宽敏感患者推荐高压缩比的zstd,如果是cpu敏感患者推荐lz4 lz4和zstd底层都使用的是lz77算法,具体实现逻辑不同&am…...
C 语 言 --- 扫 雷 游 戏(初 阶 版)
C 语 言 --- 扫 雷 游 戏 初 阶 版 代 码 全 貌 与 功 能 介 绍扫雷游戏的功能说明游 戏 效 果 展 示游 戏 代 码 详 解game.htest.cgame.c 总结 💻作 者 简 介:曾 与 你 一 样 迷 茫,现 以 经 验 助 你 入 门 C 语 言 💡个 人 主…...
黑鲨外设2025春季新品发布会:全球首款“冷暖双控”鼠标亮相!
据可靠消息称,电竞外设领域的创新引领者——黑鲨外设,正式官宣将于2025年3月28日17:00召开主题为“究极体验,竞在其中”春季新品发布会。据悉,此次新品发布会将于黑鲨游戏外设和黑鲨游戏手机官方平台同步直播,…...
SpringBoot-MVC配置类与 Controller 的扫描
文章目录 前言一、自动配置类位置二、自动配置类解析2.1 WebMvcAutoConfiguration2.1.1 EnableWebMvcConfiguration 2.2 DispatcherServletAutoConfiguration 三、RequestMapping 的扫描过程3.1 RequestMappingHandlerMapping#afterPropertiesSet3.2 RequestMappingHandlerMapp…...
Nexus L2 L3基本配置
接口基本配置 N7K上所有端口默认处于shutdown状态; N5K上所有端口默认处于no shutdown状态(所有端口都是switchport) 默认所有接口都是三层route模式, 只有当线卡不支持三层的时候, 接口才会处于二层switchport模式 show run all | in “system default” 创建SVI口需要提前打…...
asp.net 4.5在医院自助系统中使用DeepSeek帮助医生分析患者报告
环境: asp.net 4.5Visual Studio 2015本地已经部署deepseek-r1:1.5b 涉及技术 ASP.NET MVC框架用于构建Web应用程序。使用HttpWebRequest和HttpWebResponse进行HTTP请求和响应处理。JSON序列化和反序列化用于构造和解析数据。SSE(服务器发送事件…...
LCCI ESG 中英联合认证国际分析师适合的岗位
LCCI ESG中英联合认证国际分析师领域热门岗位大揭秘!🌍 大家好!今天我们来探讨LCCI ESG中英联合认证国际分析师领域的热门岗位,看看是否有适合你的选择。 1️⃣ LCCI ESG中英联合认证国际分析师报告专员:主要负责编制…...
AGI成立的条件
AGI(通用人工智能)的成立需满足多项核心条件,这些条件既涵盖技术能力层面的突破,也涉及伦理与认知维度的考量。 一、通用性与多任务处理能力 跨领域泛化能力 AGI需具备类似人类的通用性,能够灵活切换不同领域…...
论文阅读:2023 EMNLP SeqXGPT: Sentence-level AI-generated text detection
总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 SeqXGPT: Sentence-level AI-generated text detection https://aclanthology.org/2023.emnlp-main.73/ https://github.com/Jihuai-wpy/SeqXGPT https://www.doubao.com/…...
解决python配置文件类configparser.ConfigParser,插入、读取数据,自动转为小写的问题
配置类 [Section1] Key_AAA Value[Section2] AnotherKey Value默认情况下,ConfigParser会将ini配置文件中的KEY,转为小写。 重载后配置类: 继承类从configparser.ConfigParser改为configparser.RawConfigParser重载方法optionxform&#…...
超图神经网络的详细解析与python示例
扩展传统集合关系至超边结构,处理高阶交互问题。 有关人工智能的数学基础之逻辑、集合论和模糊理论:看我文章人工智能的数学基础之逻辑、集合论和模糊理论-CSDN博客 一、超图神经网络概述 超图神经网络(Hypergraph Neural Network࿰…...
机器视觉中图像的腐蚀和膨胀是什么意思?它能用来做什么?
腐蚀(Erosion)和膨胀(Dilation)是两种基本的形态学操作,通常用于二值图像(黑白图像)的处理。它们是形态学图像处理的基础,广泛应用于图像分割、边缘检测、噪声去除等任务。 1…...
破局 MySQL 死锁:深入理解锁机制与高效解决方案
死锁的原理 1. 什么是死锁? 当 多个事务 在并发执行时,每个事务都 持有其他事务需要的锁,同时又在 等待对方释放锁,导致所有事务都无法继续执行的状态,称为 死锁(Deadlock)。 2. 死锁的四个必要…...
机器学习——分类、回归、聚类、LASSO回归、Ridge回归(自用)
纠正自己的误区:机器学习是一个大范围,并不是一个小的方向,比如:线性回归预测、卷积神经网络和强化学都是机器学习算法在不同场景的应用。 机器学习最为关键的是要有数据,也就是数据集 名词解释:数据集中的…...
脚本语言 Lua
概念 Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译、运行。Lua脚本可以很容易地被C/C 代码调用,也可以反过来调用C/C的函数,这使得Lua在应用程序中可以被广泛应用。Lua并没有提供强大的库,它是不适合作为开发独立应…...
Spring相关面试题
目录 Spring中常用的注解有哪些 Spring Boot中RestController和Controller注解有什么区别? Spring的注解requestBody和responseBody的区别 说说Bean和componentscan的区别 简单介绍一下springboot Spring Boot有哪些常用的Starter依赖? 说说sprin…...
Python学习- 数据结构类型
一. list list_data [10, 20, 30]列表:是一个不限制类型,可增加,修改,删除的数据类型 可操作的方法:append,extend, pop,del ,insert append: 可向list最后一个位置添加一个元…...
Azure Delta Lake、Databricks和Event Hubs实现实时欺诈检测
设计Azure云架构方案实现Azure Delta Lake和Azure Databricks,结合 Azure Event Hubs/Kafka 摄入实时数据,通过 Delta Lake 实现 Exactly-Once 语义,实时欺诈检测(流数据写入 Delta Lake,批处理模型实时更新࿰…...
【从零开始学习计算机科学】软件测试(十)嵌入式系统测试、游戏开发与测试过程、移动应用软件测试 与 云应用软件测试
【从零开始学习计算机科学】软件测试(十)嵌入式系统测试、游戏开发与测试过程、移动应用软件测试 与 云应用软件测试 嵌入式系统测试测试策略及测试流程嵌入式软件测试问题及测试方法嵌入式软件的测试流程游戏开发与测试过程游戏开发与通用软件的开发过程区别游戏测试主要内容…...
C#零基础入门篇(18. 文件操作指南)
## 一、文件操作基础 在C#中,文件操作主要通过System.IO命名空间中的类来实现,例如File、FileStream、FileInfo等。 ## 二、常用文件操作方法 ### (一)文件读取 1. **使用File.ReadAllText方法读取文件内容为字符串** …...
深入探究 JVM 堆的垃圾回收机制(一)— 判活
垃圾回收分为两步:1)判定对象是否存活。2)将“消亡”的对象进行内存回收。 1 判定对象存活 可达性分析算法:通过一系列“GC Roots”对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,…...