第12章:优化并发_《C++性能优化指南》notes
优化并发
- 一、并发基础与优化核心知识点
- 二、关键代码示例与测试
- 三、关键优化策略总结
- 四、性能测试方法论
- 多选题
- 设计题
- 答案与详解
- 多选题答案:
- 设计题答案示例
一、并发基础与优化核心知识点
- 线程 vs 异步任务
- 核心区别:
std::thread
直接管理线程,std::async
由运行时决定异步策略(可能用线程池)。 - 优化点:频繁创建线程开销大,优先用
std::async
。
- 原子操作与内存序
- 原子类型:
std::atomic<T>
确保操作不可分割。 - 内存序:
memory_order_relaxed
(无同步)到memory_order_seq_cst
(全序同步)。
- 锁的精细控制
- 锁类型:
std::mutex
、std::recursive_mutex
、std::shared_mutex
。 - 优化技巧:缩短临界区、避免嵌套锁、用
std::lock_guard
/std::unique_lock
自动管理。
- 条件变量与生产者-消费者
- 使用模式:
wait()
搭配谓词防止虚假唤醒,notify_one()
/notify_all()
通知。
- 无锁数据结构
- 适用场景:高并发计数器、队列等,减少锁竞争。
二、关键代码示例与测试
示例1:原子操作 vs 互斥锁的性能对比
#include <iostream>
#include <atomic>
#include <mutex>
#include <thread>
#include <vector>
#include <chrono>constexpr int kIncrements = 1'000'000;// 使用互斥锁的计数器
struct MutexCounter {int value = 0;std::mutex mtx;void increment() {std::lock_guard<std::mutex> lock(mtx);++value;}
};// 使用原子操作的计数器
struct AtomicCounter {std::atomic<int> value{0};void increment() {value.fetch_add(1, std::memory_order_relaxed);}
};template<typename Counter>
void test_performance(const std::string& name) {Counter counter;auto start = std::chrono::high_resolution_clock::now();std::vector<std::thread> threads;for (int i = 0; i < 4; ++i) {threads.emplace_back([&counter] {for (int j = 0; j < kIncrements; ++j) {counter.increment();}});}for (auto& t : threads) t.join();auto end = std::chrono::high_resolution_clock::now();auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();std::cout << name << " Result: " << counter.value << ", Time: " << duration << "ms\n";
}int main() {test_performance<MutexCounter>("Mutex Counter");test_performance<AtomicCounter>("Atomic Counter");return 0;
}
编译命令:
g++ -std=c++11 -O2 -pthread atomic_vs_mutex.cpp -o atomic_vs_mutex
输出示例:
Mutex Counter Result: 4000000, Time: 182ms
Atomic Counter Result: 4000000, Time: 32ms
结论:原子操作在高并发下性能显著优于互斥锁。
示例2:线程池实现(减少线程创建开销)
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>class ThreadPool {
public:ThreadPool(size_t num_threads) : stop(false) {for (size_t i = 0; i < num_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, class... Args>auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {using return_type = decltype(f(args...));auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));std::future<return_type> res = task->get_future();{std::unique_lock<std::mutex> lock(queue_mutex);tasks.emplace([task] { (*task)(); });}condition.notify_one();return res;}~ThreadPool() {{std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (std::thread& worker : workers)worker.join();}private:std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop;
};int main() {ThreadPool pool(4);std::vector<std::future<int>> results;for (int i = 0; i < 8; ++i) {results.emplace_back(pool.enqueue([i] {std::cout << "Task " << i << " executed\n";return i * i;}));}for (auto& result : results)std::cout << "Result: " << result.get() << std::endl;return 0;
}
编译命令:
g++ -std=c++11 -O2 -pthread thread_pool.cpp -o thread_pool
输出示例:
Task Result: Task 3Task 1Task 20 executedexecuted
Task 5 executed
Task 40 executed
Task 7Task 6 executedexecutedexecutedexecutedResult: 1
Result: 4
Result: 9
Result: 16
Result: 25
Result: 36
Result: 49
结论:线程池复用线程,减少频繁创建销毁的开销。
示例3:使用无锁队列提升并发
#include <iostream>
#include <atomic>
#include <thread>template<typename T>
class LockFreeQueue {
public:struct Node {T data;Node* next;Node(const T& data) : data(data), next(nullptr) {}};LockFreeQueue() : head(new Node(T())), tail(head.load()) {}void push(const T& data) {Node* newNode = new Node(data);Node* prevTail = tail.exchange(newNode);prevTail->next = newNode;}bool pop(T& result) {Node* oldHead = head.load();if (oldHead == tail.load()) return false;head.store(oldHead->next);result = oldHead->next->data;delete oldHead;return true;}private:std::atomic<Node*> head;std::atomic<Node*> tail;
};int main() {LockFreeQueue<int> queue;// 生产者线程std::thread producer([&] {for (int i = 0; i < 10; ++i) {queue.push(i);std::this_thread::sleep_for(std::chrono::milliseconds(10));}});// 消费者线程std::thread consumer([&] {int value;while (true) {if (queue.pop(value)) {std::cout << "Consumed: " << value << std::endl;if (value == 9) break;}}});producer.join();consumer.join();return 0;
}
编译命令:
g++ -std=c++11 -O2 -pthread lockfree_queue.cpp -o lockfree_queue
输出示例:
Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Consumed: 7
Consumed: 8
Consumed: 9
结论:无锁队列减少锁争用,适合高并发场景。
三、关键优化策略总结
-
减少锁竞争:
- 缩小临界区范围。
- 使用读写锁(
std::shared_mutex
)区分读写操作。
-
利用原子操作:
- 简单计数器优先用
std::atomic
。 - 适当选择内存序(如
memory_order_relaxed
)。
- 简单计数器优先用
-
异步与线程池:
- 避免频繁创建线程,使用
std::async
或自定义线程池。
- 避免频繁创建线程,使用
-
无锁数据结构:
- 在CAS(Compare-And-Swap)安全时使用,但需注意ABA问题。
-
缓存友好设计:
- 避免false sharing(用
alignas
对齐或填充字节)。
- 避免false sharing(用
四、性能测试方法论
-
基准测试:
- 使用
std::chrono
精确测量代码段耗时。 - 对比不同实现的吞吐量(如ops/sec)。
- 使用
-
压力测试:
- 模拟高并发场景,观察资源竞争情况。
-
工具辅助:
- Valgrind检测内存问题。
- perf分析CPU缓存命中率。
多选题
-
下列哪些情况可能导致数据竞争?
A. 多个线程同时读取同一变量
B. 一个线程写,另一个线程读同一变量
C. 使用互斥量保护共享变量
D. 使用原子变量操作 -
关于
std::async
和std::thread
的选择,正确的说法是?
A.std::async
默认启动策略是延迟执行
B.std::thread
更适合需要直接控制线程生命周期的场景
C.std::async
会自动管理线程池
D.std::thread
无法返回计算结果 -
以下哪些操作可能引发死锁?
A. 在持有锁时调用外部未知代码
B. 对多个互斥量使用固定顺序加锁
C. 递归互斥量(std::recursive_mutex
)的嵌套加锁
D. 未及时释放条件变量关联的锁 -
关于原子操作的内存顺序,正确的说法是?
A.memory_order_relaxed
不保证操作顺序
B.memory_order_seq_cst
会降低性能但保证全局顺序
C.memory_order_acquire
仅保证读操作的可见性
D. 原子操作必须与volatile
关键字结合使用 -
优化同步的合理手段包括:
A. 将大临界区拆分为多个小临界区
B. 使用无锁数据结构替代互斥量
C. 通过std::future
传递计算结果
D. 在单核系统上使用忙等待(busy-wait) -
关于条件变量的正确使用方式:
A. 必须在循环中检查谓词
B.notify_one()
比notify_all()
更高效
C. 可以脱离互斥量单独使用
D. 虚假唤醒(spurious wakeup)是必须处理的 -
以下哪些是"锁护送"(Lock Convoy)的表现?
A. 多个线程频繁争抢同一互斥量
B. 线程因锁竞争频繁切换上下文
C. 互斥量的持有时间极短
D. 使用读写锁(std::shared_mutex
) -
减少共享数据竞争的方法包括:
A. 使用线程局部存储(TLS)
B. 复制数据到各线程独立处理
C. 通过消息队列传递数据
D. 增加互斥量的数量 -
关于
std::promise
和std::future
的正确说法是:
A.std::promise
只能设置一次值
B.std::future
的get()
会阻塞直到结果就绪
C. 多个线程可以共享同一个std::future
对象
D.std::async
返回的std::future
可能延迟执行 -
关于原子变量与互斥量的对比,正确的说法是:
A. 原子变量适用于简单数据类型
B. 互斥量能保护复杂操作序列
C. 原子变量的fetch_add
是原子的
D. 互斥量比原子变量性能更好
设计题
- 实现一个线程安全的无锁(lock-free)队列
要求:
- 使用原子操作实现
push
和pop
- 处理ABA问题
- 提供测试代码验证并发操作正确性
- 设计一个生产者-消费者模型
要求:
- 使用
std::condition_variable
和std::mutex
- 队列长度限制为固定大小
- 支持多生产者和多消费者
- 提供测试代码模拟并发场景
- 实现基于
std::async
的并行任务执行器
要求:
- 支持提交任意可调用对象
- 自动回收已完成的任务资源
- 限制最大并发线程数为CPU核心数
- 测试代码展示并行加速效果
- 优化高竞争场景下的计数器
要求:
- 使用线程局部存储(TLS)分散写操作
- 定期合并局部计数到全局变量
- 对比普通原子计数器与优化版本的性能差异
- 提供测试代码和性能统计输出
5 实现一个读写锁(Read-Write Lock)
要求:
- 支持多个读者或单个写者
- 避免写者饥饿(writer starvation)
- 基于
std::mutex
和std::condition_variable
实现 - 测试代码验证读写操作的互斥性
答案与详解
多选题答案:
-
B
解析:数据竞争的条件是至少一个线程写且无同步措施。A只有读不冲突,C/D有同步机制。 -
B, D
解析:std::async
默认策略非延迟(C++11起为std::launch::async|deferred
),B正确,D因std::thread
无直接返回值机制正确。 -
A, C
解析:A可能导致回调中再次加锁;C递归锁允许同一线程重复加锁但需对应解锁次数,误用仍可能死锁。 -
A, B
解析:memory_order_relaxed
无顺序保证,B正确,C中acquire
保证后续读的可见性,D错误(原子操作无需volatile
)。 -
A, B, C
解析:D在单核忙等待浪费CPU,其余均为有效优化手段。 -
A, B, D
解析:C错误,条件变量必须与互斥量配合使用。 -
A, B
解析:锁护送表现为频繁争抢导致线程切换,C短持有时间反而减少竞争,D无关。 -
A, B, C
解析:D增加锁数量可能加剧竞争,其余均为减少竞争的有效方法。 -
A, B, D
解析:C错误,std::future
不可多线程同时调用get()
。 -
A, B, C
解析:D错误,互斥量在低竞争时性能可能更差。
设计题答案示例
- 无锁队列实现(部分代码)
#include <atomic>
#include <memory>template<typename T>
class LockFreeQueue {
private:struct Node {std::shared_ptr<T> data;std::atomic<Node*> next;Node() : next(nullptr) {}};std::atomic<Node*> head;std::atomic<Node*> tail;public:LockFreeQueue() : head(new Node), tail(head.load()) {}void push(T value) {Node* new_node = new Node;new_node->data = std::make_shared<T>(std::move(value));Node* old_tail = tail.load();while (!old_tail->next.compare_exchange_weak(nullptr, new_node)) {old_tail = tail.load();}tail.compare_exchange_weak(old_tail, new_node);}std::shared_ptr<T> pop() {Node* old_head = head.load();while (old_head != tail.load()) {if (head.compare_exchange_weak(old_head, old_head->next)) {std::shared_ptr<T> res = old_head->next->data;delete old_head;return res;}}return nullptr;}
};// 测试代码
int main() {LockFreeQueue<int> queue;queue.push(42);auto val = queue.pop();if (val && *val == 42) {std::cout << "Test passed!\n";}return 0;
}
- 生产者-消费者模型
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>template<typename T>
class SafeQueue {
private:std::queue<T> queue;std::mutex mtx;std::condition_variable cv;size_t max_size;public:SafeQueue(size_t size) : max_size(size) {}void push(T item) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this] { return queue.size() < max_size; });queue.push(std::move(item));cv.notify_all();}T pop() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this] { return !queue.empty(); });T val = std::move(queue.front());queue.pop();cv.notify_all();return val;}
};// 测试代码
int main() {SafeQueue<int> q(10);std::thread producer([&q] {for (int i = 0; i < 10; ++i) {q.push(i);}});std::thread consumer([&q] {for (int i = 0; i < 10; ++i) {int val = q.pop();std::cout << "Got: " << val << '\n';}});producer.join();consumer.join();return 0;
}
其他设计题目的答案, 稍后补充
相关文章:
第12章:优化并发_《C++性能优化指南》notes
优化并发 一、并发基础与优化核心知识点二、关键代码示例与测试三、关键优化策略总结四、性能测试方法论多选题设计题答案与详解多选题答案: 设计题答案示例 一、并发基础与优化核心知识点 线程 vs 异步任务 核心区别:std::thread直接管理线程…...
Linux操作系统7- 线程同步与互斥7(RingQueue环形队列生产者消费者模型改进)
上篇文章:Linux操作系统7- 线程同步与互斥6(POSIX信号量与环形队列生产者消费者模型)-CSDN博客 本篇代码仓库:myLerningCode/l36 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一. 单生产单消费单保…...
学有所记——初探向量数据库Weaviate
目标: 了解向量数据库的连接、建库、插入数据、查询数据等基本用法以及关于语义相似度的一些基本概念。 背景: 前段时间尝试在自己的电脑上搭建OllamaDify平台,体验并探索大模型的强大功能。在使用过程中,尤其是在搭建RAG知识库…...
Ardupilot开源无人机之Geek SDK进展2025Q2
Ardupilot开源无人机之Geek SDK进展2025Q2 1. 源由2. 内容汇总2.1 【jetson-fpv】“Caution - Hot surface. Dont touch.”2.2 【jetson-fpv】1080P/720P显示设备配置 3. 遗留问题3.1 高优先级3.1.1 【jetson-fpv】1080P60FPS AI分析视频卡顿,丢包3.1.2 【jetson-fp…...
深入理解K8s与Docker的关系:容器化技术的双雄
友情提示:本文内容由银河易创(https://ai.eaigx.com)AI创作平台gpt-4-turbo模型生成,仅供参考。 在现代云计算及微服务架构的发展中,Docker与Kubernetes(K8s)作为两大核心技术,被广泛…...
QT高效文件I/O编程--实用指南与最佳实践
概述 在软件开发过程中,文件输入输出(I/O)操作是数据持久化和交换的核心部分。无论是简单的日志记录还是复杂的数据集处理,高效的文件I/O操作对于应用的整体性能至关重要 最佳实践 一、选择合适的文件模式 正确选择文件打开模式是确保操作意图明确且安全的第一步。不同…...
QT记事本
记事本应用程序提供了基本的文本编辑功能,支持文件的新建、打开、保存和另存为操作,同时具备修改提示和关闭窗口时的保存确认功能。使用 UTF - 8 编码确保了对多语言文本的支持。 1. 项目整体结构 main.cpp:程序的入口点,负责初…...
【leetcode hot 100 84】柱状图中最大的矩形
解法一:单调栈 class Solution {public int largestRectangleArea(int[] heights) {int len heights.length;int area 0;// 先做一些特殊判断if(len0){return 0;}if(len1){return heights[0];}// 进入栈后发现后面更短,可以得到当前这个能勾勒的面积 …...
Spring----ioc
1.Spring 是什么? 通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说, 还是⽐较抽象. 我们⽤⼀句更具体的话来概括Spring, 那就…...
C++——重载
目录 一、函数重载 基本概念 函数重载的条件 编程示例 代码讲解 函数重载的注意事项 二、运算符重载 什么是运算符重载? 运算符重载的实质是什么? 运算符重载函数的写法 运算符重载的基本语法 可重载的运算符列表 基本原则 编程示例 代码解…...
答疑解惑:EMC VMAX3 MMCS控制台不定期重启原因分析
今天有个朋友咨询他们有一台EMC的VMAX100k设备,其中MMCS2的管理控制台定期重启,但始终无法找到重启原因,稍微花了点时间,帮客户看了下。先说结论,MMCS2确实不定期发生重启,每次reboot都是一样的message信息…...
单例模式(Singleton Pattern)
单例模式(Singleton Pattern) 任务管理器可以作为一个全局的任务配置管理类,使用单例模式保证全局只有一个实例。这样你可以避免在应用程序中创建多个任务管理对象,保持配置参数的统一。 示例: class TaskManager { …...
树莓派超全系列文档--(8)RaspberryOS实用程序
RaspberryOS实用程序 实用程序kmsprintvclogvcgencmdvcosversionget_throttledmeasure_tempmeasure_clock [clock]measure_volts [block]otp_dumpget_config [configuration item|int|str]get_mem typecodec_enabled [type]mem_oommem_reloc_statsread_ring_osc 文章来源&#…...
Rust 与 FFmpeg 实现视频水印添加:技术解析与应用实践
引言 在短视频、直播、影视制作等领域,视频水印是一种常见的工具,用于保护版权、提升品牌辨识度或满足合规性要求。然而,开发者在实现水印添加时往往面临以下挑战: 手动处理效率低:使用图像编辑软件(如 P…...
绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享
文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好,今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下,即使没有公网IP,你也能随时随地远程访问自己…...
如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载?
大白话如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载? 在 React 项目里,有时候组件功能多、体积大,要是一次性把所有组件都加载进来,网页加载速度就会变慢。而 React 提供了 React.lazy 和 Suspense 这两个好东西…...
虫洞数观系列一 | 豆瓣电影TOP250数据采集与MySQL存储实战
目录 系列文章 1. 引言 2 技术栈Request 2.1请求头headers 2.2查找定位信息 2.3处理网页html结构化数据 2.4每页url规律 2.5逐条查找所需信息 2.6完整代码 3 数据存储至mysql 3.1新建数据库 3.2编写数据库写入py文件 3.2.1构建1个执行sql语句的函数 3.2.2构造一个…...
模型 阿米巴模式
系列文章分享模型,了解更多👉 模型_思维模型目录。小团队独立经营,企业活力无限。 1 阿米巴模式的应用 1.1 日航重生(航空业成功案例) 应用领域 航空运输业破产重组与组织激活 案例名称 日本航空(JAL&…...
针对stm32F103C8t6芯片调节USB串口的经验
1、首先这是自己手搓的板子,对于之前一直没有了解过USB这方面,则这个针对USB部分没有设计上拉电阻,造成不管怎么调节PC端都没有反应。 图一 这个没有添加1.5K电阻 这个D+位置应该再接一个1.5KR的电阻如图2所示 图2 这样调节的话PC端就可以识别到USB串口,但是这是串口还是会…...
JVM详解(包括JVM内存模型与GC垃圾回收)
📖前言: 学会使用Java对于一个程序员是远远不够的。Java语法的掌握只是一部分,另一部分就是需要掌握Java内部的工作原理,从编译到运行,到底是谁在帮我们完成工作的? 接下来着重对Java虚拟机,也就…...
解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…...
【Linux网络】——Socket网络编程
前言 在当今数字化的时代,网络通信已经成为计算机领域不可或缺的一部分。无论是日常的网页浏览、社交媒体交互,还是大规模的企业级数据传输,都离不开高效可靠的网络通信。而在Linux操作系统中,Socket网络编程是实现各种网络应用的…...
基于javaweb的SpringBoot雪具商城系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
Android 简化图片加载与显示——使用Coil和Kotlin封装高效工具类
为了简化使用Coil加载网络图片和GIF的过程,我们可以封装一个工具类。这个工具类将包括初始化ImageLoader的方法、加载图片到ImageView的方法,以及可能的其他便捷方法,如加载圆形图片、设置占位图等。下面是一个示例: 首先&#x…...
Flink watermark的时间字段有空值,建表的时候,如何处理
在 Flink 中处理时间字段存在空值时,需通过 表定义阶段的特殊处理 和 Watermark 生成策略调整 来避免因空值导致的窗口计算异常或任务失败。以下是具体解决方案及实现方法: 1. 空值处理核心策略 1.1 查询时,过滤空值数据(推荐&am…...
关于matlab和python谁快的问题
关于matlab和python谁快的问题,python比matlab在乘法上快10倍,指数计算快4倍,加减运算持平,略慢于matlab。或许matlab只适合求解特征值。 import torch import timen 50000 # 矩阵规模 M torch.rand(n, 31)start_time time.t…...
【DevOps】DevOps and CI/CD Pipelines
DevOps 是一种将开发与运维实践相结合的模式,旨在缩短软件开发周期并交付高质量软件。 DevOps 是什么? 开发团队与运维团队之间的协作 • 持续集成与持续交付(CI/CD) • 流程自动化 • 基础设施即代码(IaC)…...
ROS--IMU数据包
IMU惯性测量单元 一:IMU二:ROS中三:IMU数据包三:总结 提示:以下是本篇文章正文内容,下面案例可供参考 一:IMU IMU(Inertial Measurement Unit,惯性测量单元)…...
【机器学习】手撕封装PCA——将高维数据映射到低维数据的过程
PCA将高维数据映射到低维数据的过程 一、摘要二、PCA的降维思路三、PCA代码实现降维过程3.1 PCA类的实现与封装3.2 PCA类的使用示例 四、PCA的恢复过程 一、摘要 本文详细介绍了主成分分析法(PCA)在高维数据降维中的应用。首先,阐述了PCA的基…...
LangChain开发(七)自定义输出格式(JSON/XML/YAML)
文章目录 JSON结构输出未使用PydanticPydantic流式处理 XML结构输出xml输出指定字段 YAML输出源码地址参考资料 JSON结构输出 虽然一些模型提供商支持内置的方法返回结构化输出,但并非所有都支持。我们可以使用输出解析器来帮助用户通过指示指定任意的JSON模型&…...
RustDesk部署到linux(自建服务器)
简介 RustDesk是一款开源的远程桌面软件,由中国开发者开发,使用Rust编程语言构建。它支持跨平台运行,可以在Windows、macOS、Linux、iOS、Android和Web等多个平台上使用。RustDesk的主要功能包括远程桌面访问、文件传输、文本聊天等&…...
分布式锁,redisson,redis
目录 什么是分布式锁分布式锁解决什么问题分布式锁的特点使用分布式锁的场景怎么使用分布式锁1. 添加依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁 什么是分布式锁 分布式锁是一种锁机制,用于在分布式环境下,解决多个线程并发访问同一共享…...
linux常用指令(9)
加油同志们,我们离胜利不远了,再有两天我们就可以了解完linux的一些基本常用指令了,到时我们便可以进入一些shell脚本语法了,那么话不多说,来看. 1.more指令 功能描述:more指令是一个基于vi编辑器的文本过滤器,它以全屏幕的方式按页显示文本文件的内容. 基本语法…...
深入解析 JVM 内存区域及核心概念
深入解析 JVM 内存区域及核心概念 Java 虚拟机(JVM)内部划分了多个内存区域,每个区域存储不同类型的数据并承担不同的职责。本文将详细介绍以下内容: 程序计数器:记录当前线程正在执行的字节码指令及其“行号”信息&a…...
字节跳动春招研发部笔试题解
字节跳动春招研发部笔试题 1.万万没想到之聪明的编辑 我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。我发现一个发…...
java对象模型
java对象自身的存储模型JVM会给这个类创建一个instanceKlass,保存在方法区,用来在JVM层表示该Java类。 a类。当我们在Java代码中,使用new创建一个对象的时候,JVM会在栈中给对象赋值,会在堆中创建一个instanceOopDesc对…...
深入理解指针(3)(C语言版)
文章目录 前言 一、字符指针变量二、数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化2.2.1 静态初始化2.2.2 动态初始化 三、二维数组传参的本质四、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 typedef关键字4.4拓展 五、函数指针数组六、转…...
Linux内核 内存管理 物理内存初始化流程
1.ARM64页表初始化流程图 start_kernel()│▼ setup_arch() // 架构相关初始化│▼ early_fixmap_init() // 初始化Fixmap(临时映射设备树等)│▼ arm64_memblock_init() // 从设备树解析内存布局│▼ arm…...
Day23:和为s的数字
购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。 示例 1: 输入:price [3, 9, 12, 15], target 18 输出:[3,15] 或者 [15,3]示例 2&#x…...
Transformer 通关秘籍2:利用 BERT 将文本 token 化
前面两节分别通过两个代码示例展示了模型将文本转换为 token 之后是什么样的,希望你可以对此有一个感性的认识。 本节来简要介绍一下将一个连续的文本转换为 token 序列的大致过程,这个过程被称为分词,也叫 tokenization。 在你没了解这方面…...
电脑干货:万能驱动--EasyDrv8
目录 万能驱动EasyDrv8 功能介绍 主程序界面 驱动解压与安装 PE环境支持 系统部署环境 桌面环境一键解决方案 万能驱动8电脑版是由IT天空出品的一款智能识别电脑硬件并自动安装驱动的工具,一般又称为it天空万能驱动,万能驱动vip版,简称…...
18502 字符串哈希匹配字符串
18502 字符串哈希匹配字符串 ⭐️难度:中等 🌟考点:字符串hash 📖 📚 import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int…...
openmmlab介绍 一下
OpenMMLab 是由商汤科技(SenseTime)发起并维护的开源深度学习项目,专注于计算机视觉领域。它提供了一系列模块化、可扩展的工具库,旨在帮助研究者和开发者高效地实现、复现和部署前沿的视觉算法。OpenMMLab 的设计强调模块化、…...
基于javaweb的SpringBoot线上网络文件管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
【设计模式】工厂模式详解-----简单工厂模式、工厂方法模式、抽象工厂模式
工厂模式详解 一、概述 工厂模式(Factory Pattern) 是一种 创建型设计模式,用于 封装对象的创建逻辑,避免在代码中直接实例化对象,从而提高代码的 可维护性、扩展性和解耦性。 二、工厂模式分类 工厂模式包括 简单工…...
【雅思播客09】Turn Left here.
Hello everyone! And welcome to my channel! Im Reevs. Good morning! 大家好,欢迎来到懒人英语晨读栏目,我是Reevs,早上好呀。 I have a great lesson for you today. 今天我有一堂非常棒的课。 We have an elementary lesson, which is …...
初阶7 vector
本章重点 vector的介绍vector的使用vector的模拟实现 1.vector的介绍 vector就类似数据结构中的顺序表 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。 意味着可以采用下标对vector的元素 进行访问,和数…...
归并排序总结
归并排序是分治法的典型应用,把两个或k个有序的子序列合并为一个。2路归并,2合一。k路归并,k合一。内部排序通常采用2路归并排序,先将数组分成两半,分别排序,然后合并。合并的过程需要将两个有序的子数组合…...
ollama迁移已下载的单个模型到服务器
ollama迁移已下载的单个模型到服务器 场景 ollama是面向用户级的,部署和运行都很简单,是否高效就另说了。但最起码,他能充分利用用户的硬件设备,在GPU不足也能调用cpu和内存去加持。 ollama运行的模型基本是量化版本的…...
基于SSM+Vue物流信息管理系统(附源码)
预览页面 获取方式 https://gitee.com/XiaoLin_Java/communion/blob/master/README.en.md...