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

C++ 并发

C++ 并发编程是现代软件开发中的核心技术,主要用于利用多核处理器提升程序性能。C++11 及后续标准引入了完善的并发库(<thread><mutex><condition_variable> 等),使开发者能更安全地编写多线程程序。

1、std::thread

std::thread 是 C++11 引入的线程类,用于创建和管理线程。

1.1 基本使用

#include <thread>
#include <iostream>
using namespace std;// 线程函数:普通函数
void thread_func(int id) {cout << "Thread " << id << " 运行" << endl;
}int main() {// 创建线程(传入函数和参数)thread t1(thread_func, 1); thread t2([](int id) {  // 线程函数:lambda表达式cout << "Thread " << id << " 运行" << endl;}, 2);// 等待线程结束(必须调用join()或detach(),否则程序崩溃)t1.join();  // 主线程阻塞,等待t1完成t2.join();  // 主线程阻塞,等待t2完成// 或分离线程(线程独立运行,主线程不等待)// t1.detach(); // t2.detach();return 0;
}

1.2 关键特性

  • join():主线程阻塞等待子线程完成,回收线程资源。
  • detach():将线程与 std::thread 对象分离,线程后台运行,由系统自动回收资源(需确保线程访问的资源生命周期足够长)。
  • 线程对象必须被移动:std::thread 不可拷贝,只能移动(thread t2 = move(t1);)。

2、互斥锁

互斥锁(Mutex)用于保护共享资源,确保同一时间只有一个线程访问资源,避免数据竞争。

多个线程同时读写共享数据会导致数据竞争,结果是未定义行为。

  • std::mutex:基础互斥锁,提供 lock()(加锁)和 unlock()(解锁)方法(需手动配对,易出错)。
  • std::lock_guard:RAII 风格的锁管理,构造时自动加锁,析构时自动解锁(推荐,避免忘记解锁)。
  • std::unique_lock:更灵活的锁管理,支持手动 lock()/unlock()、超时等待等(适合条件变量)。

2.1 std::mutex

如果临界区中抛出异常,unlock() 可能不会被调用,导致死锁。

#include <thread>
#include <mutex>
#include <iostream>int shared_data = 0;
std::mutex data_mutex; // 用于保护 shared_datavoid increment() {for (int i = 0; i < 100000; ++i) {data_mutex.lock();   // 上锁++shared_data;       // 临界区 (Critical Section)data_mutex.unlock(); // 解锁}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final value: " << shared_data << std::endl; // 总是 200000return 0;
}

2.2 lock_guard

这是推荐的做法,它在其作用域内自动管理锁的生命周期。

#include <mutex>
#include <vector>
#include <thread>vector<int> shared_data;
mutex mtx;  // 保护shared_data的互斥锁void add_data(int val) {lock_guard<mutex> lock(mtx);  // 构造时加锁,析构时解锁(离开作用域)shared_data.push_back(val);   // 安全访问共享资源
}int main() {thread t1(add_data, 1);thread t2(add_data, 2);t1.join();t2.join();// shared_data 安全存储 [1,2] 或 [2,1]return 0;
}

2.3 std::unique_lock

std::lock_guard 更灵活(但开销稍大),可以延迟上锁、手动解锁、转移所有权。

void flexible_function() {std::unique_lock<std::mutex> ulock(data_mutex, std::defer_lock); // 延迟上锁// ... 做一些不需要锁的操作 ...ulock.lock(); // 现在需要锁了,手动上锁// ... 操作共享数据 ...ulock.unlock(); // 可以手动提前解锁// ... 更多操作 ...// ulock 析构时,如果还持有锁,会自动解锁
}

2.4 条件变量(std::condition_variable)

条件变量用于线程间通信,使线程能等待某个条件满足后再继续执行(如生产者 - 消费者模型)。

  • wait(lock, predicate):阻塞线程,释放锁并等待通知;被唤醒后重新获取锁,检查条件是否满足(不满足则继续等待)。
  • notify_one():唤醒一个等待的线程。
  • notify_all():唤醒所有等待的线程。
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> data_queue;
std::mutex queue_mutex;
std::condition_variable data_cond;void data_preparation_thread() {int data = 0;while (true) {std::this_thread::sleep_for(std::chrono::seconds(1));{std::lock_guard<std::mutex> lk(queue_mutex);data_queue.push(++data);std::cout << "Prepared data: " << data << std::endl;} // lock_guard 超出作用域,锁释放data_cond.notify_one(); // 通知一个等待的消费者线程}
}void data_processing_thread() {while (true) {std::unique_lock<std::mutex> lk(queue_mutex);// 等待条件满足:Lambda 函数返回 true 时才继续,否则释放锁并等待通知data_cond.wait(lk, [] { return !data_queue.empty(); }); // 被 notify 后,重新获取锁,并检查条件int data = data_queue.front();data_queue.pop();lk.unlock(); // 处理数据不需要锁,提前解锁std::cout << "Processed data: " << data << std::endl;// 处理数据...}
}int main() {std::thread t1(data_preparation_thread);std::thread t2(data_processing_thread);t1.join();t2.join();
}

2.5 原子操作 (std::atomic)

std::atomic 提供无锁的原子操作,用于简单的计数器、标志位等场景,性能优于锁(无需上下文切换)。

#include <atomic>atomic<int> counter(0);  // 原子计数器(线程安全)void increment() {for (int i = 0; i < 1000; ++i) {counter++;  // 原子操作,无数据竞争}
}int main() {thread t1(increment);thread t2(increment);t1.join();t2.join();cout << "计数器结果: " << counter << endl;  // 必然是2000(无竞争)return 0;
}

3、异步

3.1 std::async 和 std::future

std::async 用于启动异步任务,返回 std::future 对象,通过 future 获取任务结果(避免手动管理线程)。

#include <future>
#include <iostream>int calculate() {std::this_thread::sleep_for(std::chrono::seconds(2));return 42;
}int main() {// 启动一个异步任务// std::launch::async: 强制在新线程运行// std::launch::deferred: 延迟计算,直到调用 get() 时才在当前线程运行std::future<int> result_future = std::async(std::launch::async, calculate);std::cout << "Doing other work..." << std::endl;// 获取结果。如果计算未完成,会阻塞等待。int result = result_future.get(); std::cout << "The answer is: " << result << std::endl;// result_future.get() 只能调用一次!return 0;
}

3.2 std::promise 和 std::future

用于在线程之间传递结果,提供更精细的控制。

void do_work(std::promise<int> result_promise) {std::this_thread::sleep_for(std::chrono::seconds(1));result_promise.set_value(100); // 设置结果值// 如果发生异常: result_promise.set_exception(std::current_exception());
}int main() {std::promise<int> prom;std::future<int> fut = prom.get_future(); // 获取与 promise 关联的 futurestd::thread t(do_work, std::move(prom)); // 将 promise 移动到新线程int result = fut.get(); // 阻塞直到 promise 设置值std::cout << "Result: " << result << std::endl;t.join();return 0;
}

4、常见问题

  1. 什么是数据竞争 (Data Race)?如何避免?
    当两个或多个线程在没有同步的情况下并发访问同一个内存位置,并且至少有一个是写操作时,就会发生数据竞争。其结果是不确定的,是未定义行为。
    避免方法

    • 使用互斥锁 (std::mutex) 保护共享数据。
    • 将共享数据改为原子变量 (std::atomic)。
    • 重新设计程序,避免共享(例如,每个线程处理自己的数据副本,最后合并)。
  2. std::lock_guardstd::unique_lock 有什么区别?

    • std::lock_guard轻量级作用域锁。构造时上锁,析构时解锁。不能手动控制锁的时机。
    • std::unique_lock重量级更灵活。可以延迟上锁、手动解锁、递归上锁、转移所有权。支持与条件变量一起使用。如果不需要 std::unique_lock 的特殊功能,应优先使用 std::lock_guard
  3. 什么是死锁 (Deadlock)?如何预防?
    死锁是指两个或多个线程相互等待对方持有的资源,导致所有线程都无法继续执行的状态。
    产生条件(四个必要条件,缺一不可):

    1. 互斥:资源一次只能被一个线程持有。
    2. 持有并等待:线程持有一些资源,同时请求其他线程持有的资源。
    3. 不可剥夺:资源只能由持有它的线程主动释放。
    4. 循环等待:存在一个线程资源的循环等待链。
      预防策略
    5. 按固定顺序上锁:所有线程以相同的全局顺序获取锁(例如,总是先锁 mutex A,再锁 mutex B)。
    6. 使用 std::lock() 函数:它可以一次性锁定多个互斥量,且不会产生死锁(内部使用死锁避免算法)。
    std::mutex mutex1, mutex2;
    void safe_function() {std::lock(mutex1, mutex2); // 同时锁住两个,避免死锁std::lock_guard<std::mutex> lk1(mutex1, std::adopt_lock); // 接管已锁的mutex1std::lock_guard<std::mutex> lk2(mutex2, std::adopt_lock); // 接管已锁的mutex2// ...
    }
    
    1. 避免嵌套锁,或者使用超时机制 (std::timed_mutex)。
  4. 什么是虚假唤醒?std::condition_variable::wait 为什么要用循环检查条件?
    虚假唤醒是指等待中的线程在没有收到任何通知的情况下被操作系统唤醒。这是为了性能考虑,但会导致程序错误。
    解决方法:始终在循环中检查等待条件。

data_cond.wait(lk, [] { return !data_queue.empty(); });
// 这等价于:
// while (!predicate()) { // 循环检查!
//     data_cond.wait(lk);
// }

Lambda 函数(谓词)确保了即使发生虚假唤醒,线程也会再次检查条件是否真正满足,如果不满足会继续等待。

  1. std::async 的启动策略 std::launch::asyncstd::launch::deferred 有什么区别?
  • std::launch::async异步执行。强制要求在新创建的线程上执行任务。
  • std::launch::deferred延迟执行。任务不会立即执行,而是延迟到对返回的 std::future 调用 get()wait() 时,在调用者的线程中同步执行
  • 如果不指定策略,标准允许实现自由选择,这可能导致不确定性。最佳实践是显式指定策略
  1. 什么时候该用 std::atomic,什么时候该用 std::mutex
  • 使用 std::atomic:当你要保护的数据是简单的基本类型(如 int, bool, 指针)并且操作是单一的(读、写、递增、交换等)时。性能开销远小于互斥锁。
  • 使用 std::mutex
    • 当你要保护的数据是复杂的结构(如 std::vector, std::map)。
    • 当你需要执行一组操作临界区)来保持数据的不变性时。原子操作无法保证多个操作的整体原子性。
    • 例如,检查一个 std::map 中是否存在某个键,如果不存在则插入,这个操作必须用互斥锁保护,原子操作无法完成。
  1. 如何实现一个线程安全的单例模式?
    使用 Meyers' Singleton,它依靠静态局部变量的初始化在 C++11 及以后是线程安全的这一特性。

    class Singleton {
    public:static Singleton& getInstance() {static Singleton instance; // C++11保证此初始化是线程安全的return instance;}// 删除拷贝构造函数和赋值运算符以确保唯一性Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;void doSomething() { /* ... */ }private:Singleton() = default; // 私有构造函数~Singleton() = default;
    };// 使用
    Singleton::getInstance().doSomething();
    

    在 C++11 之前,需要使用双重检查锁定模式(Double-Checked Locking Pattern),但实现起来非常复杂且容易出错。Meyers' Singleton 是现代 C++ 中的最佳实践。

  2. 如何设计一个线程池?
    线程池是管理多个线程的对象,避免频繁创建/销毁线程的开销,核心组件包括:

    1. 工作线程:预先创建的线程,循环等待任务。
    2. 任务队列:存储待执行的任务(如 std::queue<std::function<void()>>)。
    3. 互斥锁:保护任务队列的线程安全。
    4. 条件变量:通知工作线程有新任务。

    简化实现思路

    class ThreadPool {
    private:vector<thread> workers;    // 工作线程queue<function<void()>> tasks;  // 任务队列mutex mtx;condition_variable cv;bool stop;  // 停止标志// 工作线程函数:循环取任务执行void worker() {while (true) {function<void()> task;{unique_lock<mutex> lock(mtx);// 等待任务或停止信号cv.wait(lock, [this]{ return stop || !tasks.empty(); });if (stop && tasks.empty()) return;task = move(tasks.front());tasks.pop();}task();  // 执行任务}}public:// 构造函数:创建n个工作线程ThreadPool(size_t n) : stop(false) {for (size_t i = 0; i < n; ++i) {workers.emplace_back(&ThreadPool::worker, this);}}// 提交任务template<class F>void submit(F&& f) {{lock_guard<mutex> lock(mtx);tasks.emplace(std::forward<F>(f));}cv.notify_one();  // 通知工作线程}// 析构函数:停止所有线程~ThreadPool() {{lock_guard<mutex> lock(mtx);stop = true;}cv.notify_all();  // 唤醒所有线程for (auto& w : workers) {w.join();  // 等待线程结束}}
    };
    
  3. 条件变量(condition_variable)的 wait() 为什么需要传入 unique_lock

    wait() 需要在阻塞时释放锁(让其他线程有机会修改条件),被唤醒后重新获取锁(确保条件的安全性)。unique_lock 支持手动 lock()/unlock(),而 lock_guard 不支持手动解锁,因此 wait() 必须使用 unique_lock

  4. std::async 的三种启动策略有什么区别?

    std::async 有三种启动策略(C++11 定义):

    • std::launch::async:立即创建新线程执行任务,任务与主线程并行。
    • std::launch::deferred:任务延迟执行,直到调用 future::get()wait() 时,在当前线程同步执行。
    • std::launch::async | std::launch::deferred(默认):由系统决定策略(通常倾向于 async,但不保证)。

相关文章:

C++ 并发

C++ 并发编程是现代软件开发中的核心技术,主要用于利用多核处理器提升程序性能。C++11 及后续标准引入了完善的并发库(<thread>、<mutex>、<condition_variable> 等),使开发者能更安全地编写多线程程序。 1、std::thread std::thread 是 C++11 引入的线程…...

UML 5章

UML是建模语言,能够用面向对象的方法描述任何类型的系统 UML时序图:他通过对象之间发送消息的时间顺序显示多个对象之间的动态协作,重在对象之间的交互,强调时间顺序例UML状态图例...

《微服务事务管理》 - 教程

《微服务事务管理》 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-siz…...

python之socket udp服务器实现

import socket# 1. 创建 UDP Socket (SOCK_DGRAM 表示 UDP) receiver_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 2. 绑定地址和端口 receiver_address = (, 1883) # 端口号 9999 receiver_socket.bind(receiver_address)print("UDP 接收方已启动,等待…...

kylin SP3安装mysql 8.4.5

环境:OS:kylin SP3mysql:8.4.5 glibc2.17,建议安装glibc.2.28版本 查看系统glibc版本[root@localhost ~]# ldd --versionldd (GNU libc) 2.28Copyright (C) 2018 自由软件基金会。这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性或者适合某…...

Unity中是否可以禁用GC

1)Unity中可以禁用GC吗2)项目是URP管线,渲染模块CPU耗时高,经排查主要是Batches数过高,应怎样进一步排查和优化渲染批次这是第445篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习。 UWA社区主页:co…...

经典SQL语句大全

经典SQL语句大全一、基础1、说明:创建数据库CREATE DATABASE database-name2、说明:删除数据库drop database dbname3、说明:备份sql server--- 创建 备份数据的 deviceUSE masterEXEC sp_addumpdevice disk, testBack, c:\mssql7backup\MyNwind_1.dat--- 开始 备份BACKUP D…...

IvorySQL 与 deepin 完成兼容性认证,共创开源生态新篇章

近日,IvorySQL 与 deepin 操作系统成功完成了兼容性适配认证。这一里程碑式的成就标志着 IvorySQL 在国产操作系统生态中的进一步深化,为用户提供更稳定、高效的数据库解决方案。deepin 简介 深度操作系统 deepin 是一款以“简洁、美观、易用”著称的国产 Linux 发行版,拥有…...

在 Nginx 上搭建静态站点

1、新建站点的配置文件 vi /etc/nginx/conf.d/www.xxx.com.conf2、写入如下内容: server {listen 80;#listen [::]:80;server_name www.xxx.com; # 这里可以写你的域名,或者 _ 表示匹配所有 root /var/www/www.xxx.com; # 你的静态文件目录 index index.html index.htm;locat…...

使用GitHub Dork快速发现漏洞:我的第一个Bugcrowd漏洞挖掘实战

本文详细介绍了如何通过GitHub Dork技术快速发现企业敏感信息泄露漏洞,包含实用的搜索语法和实际案例,帮助安全研究人员高效挖掘漏洞。使用GitHub Dork快速发现漏洞:我的第一个Bugcrowd漏洞挖掘实战 嗨,黑客们,漏洞猎人们! 祝愿你们发现大量漏洞并获得丰厚奖励! 虽然距离…...

kylin SP3安装mysql8.0.41

环境:OS:kylin SP3mysql:8.0.41 glibc2.17,建议安装glibc.2.28版本 查看系统glibc版本[root@localhost ~]# ldd --versionldd (GNU libc) 2.28Copyright (C) 2018 自由软件基金会。这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性或者适合某…...

DIFY 项目中通过 Makefile 调用 Dockerfile 并采用 sudo make build-web 命令构建 web 镜像的方法和注意事项

DIFY 项目中通过 Makefile 调用 Dockerfile 并采用 sudo make build-web 命令构建 web 镜像的方法和注意事项pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…...

代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素、209.长度最小的子数组

704. 二分查找 思路:刷过很多次了,就是双指针思想,初始化一个在数组最左边的指针index_l,一个在最右边的指针index_r,当index_l < index_r 的时候通过判断index_l 和 index_r所确定的区间,缩小区间,最后夹逼出我们的目标值。 注意的点:最终状态会有两个 :1.l与r相等…...

从 MLPerf Storage v2.0 看 AI 训练中的存储性能与扩展能力

8 月 5 日,全球权威 AI 工程联盟 MLCommons 发布了最新的 MLPerf Storage v2.0 基准测试结果。本次评测吸引了众多厂商参与,包括 Cloud、Shared File、Fabric-Attached Block、Direct-Attached Block 这几大类存储厂商。 由于各厂商在硬件配置、节点规模和应用场景上的差异,…...

Revit二次开发 钢筋生成API(二)

2、自由钢筋生成API 创建一条无约束的自由形状钢筋。之后无法对该钢筋添加约束。public static Rebar CreateFreeForm(Document doc,RebarBarType barType,Element host,IList<IList<Curve>> curves,out RebarFreeFormValidationResult error )这个合自由钢筋生成A…...

创建会计凭证报错:FI/CO接口:待更新的不一致的FI/CO凭证标题数据(转)

问题:使用过账BAPI_ACC_DOCUMENT_POST,自动过账时,报错原因是“FI/CO接口:待更新的不一致的FI/CO凭证标题数据”。 原因: 1、如果头数据里面的公司和行项目公司是一致的,检查行项目,不要对行项目赋公司bukrs。 "it_item-comp_code = wa_account-bukrs. 2、检查金额是…...

Uri uri = new Uri(Path); 这行代码的作用

1. 语法校验 字符串里只要多一个空格、少一个 /、中文没转义,后面 HttpClient 会直接炸。 Uri 构造函数会第一时间给你抛 UriFormatException,早发现早处理。 2. 把“一串字符”升级成“有结构的零件箱” 转成 Uri 后,你就能直接拿这些字段,而不用再 Substring、IndexOf 去…...

Qt函数方法传入参数未使用-警告warning错误error提示解决

前言全局说明某些情况下,函数(方法)会传入参数,但并不一定会使用, 但是,不使用编辑器又会警告一、说明 1.1 环境: Windows 7 旗舰版 Visual Studio 2013二、未使用参数解决 原型 Q_UNUSED(未使用参数)三、示例 3.1 文件名: public:MyThread(QWidget *parent = nullptr){Q_…...

mysql 性能监控,关键指标解析与优化案例剖析

你是否经历过数据库突然变慢却无从下手的困境?某金融平台曾因慢查询堆积导致交易响应暴增300%,某电商大促期间因缓冲池命中率骤降引发订单延迟。性能问题往往具备隐蔽性和突发性特征,本文将揭示MySQL监控的核心参数与实战诊断方法。 连接池监控是性能防护的第一道防线。Thre…...

设计模式

1.分类 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享 元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责…...

Rhinoceros 8.23.25251.13001 犀牛3D建模

描述 Rhinoceros 是由美国Robert McNeel公司最新出品的专业强大的3D建模软件。软件以集百家之长为一体的发展教育理念,拥有NURBS的优秀传统建模教学方法,也有一个网格进行建模插件T-Spline,使建模方式方法有了更多的挑选,然后能创建出更传神、生动的造型。能输入和输出几十…...

Git 常用操作指南

本文为你整理了 Git 的常用操作,无论你是刚接触 Git 还是需要快速查阅,这篇指南都能帮你高效管理代码版本。 🔧 初始配置 开始使用 Git 前,先配置你的用户信息: git config --global user.name "你的用户名" git config --global user.email "你的邮箱&qu…...

《深入理解计算机系统》计算机系统漫游(一) - Invinc

本文记录《深入理解计算机系统》中第1章 计算机系统漫游 的一些知识点。本文记录《深入理解计算机系统》中第1章 计算机系统漫游 的一些知识点。第1章 计算机系统漫游 信息就是位+上下文 系统中所有的信息——包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的…...

从几何分离到语义理解:深度解析3D点云分割与语义分割的本质区别

在三维计算机视觉领域,3D点云作为真实世界场景的核心数据载体,其处理技术直接决定了机器感知环境的精度与效率。 其中,3D点云分割与语义分割是两类关键技术,尽管二者同属点云处理范畴,但在目标定位、信息输出与应用价值上存在本质差异。 前者专注于“几何层面的分离”,通…...

欧拉筛(线性筛)算法分析

前言对于寻找素数,第一时间想到的便是二重循环暴力查找,其复杂度O(n^2),通过循环中只判断到根号n可以优化一些,不过复杂度也达不到预期。在数论的学习中,我学到了埃氏筛法,O(nloglogn)的算法,而在一些数据范围达到1e7这样的题目中,也很难让人满意,于是我便学习了欧拉筛…...

2021年安徽省大数据与人工智能应用竞赛 大数据(网络赛)-高职组赛题

本套数据数据: 通过网盘分享的文件: 链接: https://pan.baidu.com/s/1ZQXoWQhCOAiGVcFOZozV1g?pwd=json 提取码: json 第二部分:大数据程序编写部分(30分) 任务一、数据抽取转化部分(5分) 1、使用sqoop将MySQL的sakila数据库中的city表中city列以C开头的数据导入到hdfs…...

Alexandresku设计的loki小对象内存分配器

Loki是由 Alexandresku 编写的一个与《Modern C++ Design》(C++设计新思维)一书配套发行的C++代码库。其中有两个文件 SmallObj.h 、SmallObj.cpp 进行内存管理,可以单独进行使用 三个class,第一层是chunk,第二层是vector<chunk> FixedAllocator,第三层是vector&l…...

C++ 内存管理

C++ 内存管理是程序设计的核心环节,直接影响程序的性能、稳定性和安全性。C++ 不像 Java、Python 等语言有自动垃圾回收机制,而是需要开发者手动管理动态内存(或通过智能指针等机制自动管理)。 1、C++ 内存分区内存区域 存储内容 生命周期 管理方式栈 (Stack) 函数参数、局…...

一些写了和没写的数学!

P8114 [Cnoi2021] 六边形战士 传送 非常好玩的题! 首先你大概率看过一些“无字证明”,其中很经典的是这个: 证明:用若干个边长为 \(1\),顶角为 \(60\) 度的菱形拼成一个边长为 \(n\) 的正六边形,三个方向的菱形个数一定相等。这是一个经典的无字证明,虽然前置的说明要费…...

【光照】[自发光Emission]以UnityURP为例

【从UnityURP开始探索游戏渲染】专栏-直达自发光的基本原理 $Cemissive=Memissive$ 自发光是物体表面主动发射光线的现象,在光照模型中通常作为独立于外部光源的附加项。其核心特点是不受其他光照影响,但可以影响周围环境。 实现流程‌定义发射颜色和强度‌:确定基础发光颜色…...

mybatis-plus初体验,解决报错Invalid value type for attribute factoryBeanObjectType: java.lang.String

解决报错Invalid value type for attribute factoryBeanObjectType: java.lang.String 推荐这位大佬的博客: https://www.cnblogs.com/muphy/p/18653627 项目结构MyBatis-Plus配置类MyBatisPlusConfig package com.example.config;import com.baomidou.mybatisplus.annotation…...

浅谈制氢电源及英飞凌解决方案

大家对氢元素肯定都不陌生,认识它基本都是从背元素周期表开始的。近年来我们身边多了很多氢的身影,从北京冬奥会的氢燃料电池大巴,再到广州南沙小虎岛电氢智慧能源站,氢也越来越被大家熟知。工业上,氢的使用可是一点都不少,自 1975 年以来,需求量增长了三倍,而且还在继…...

微算法科技(NASDAQ:MLGO)研究分布式量子计算,释放量子计算潜能

在信息时代,数据量呈指数级增长,经典计算机面临算力瓶颈。量子计算以其超强的并行处理能力,被视为下一世代计算范式的颠覆者。然而,单个量子处理器的脆弱性和制造难度限制了其广泛应用。微算法科技(NASDAQ:MLGO)研发团队研究通过分布式量子计算模型,将多个量子计算节点连…...

AI 重塑招聘三角:Moka 招聘智能体如何实现 HR、候选人与企业的三方共赢

AI 重塑招聘三角:Moka 招聘智能体如何实现 HR、候选人与企业的三方共赢在人才竞争进入白热化的今天,招聘早已不是 HR 单方面的 “筛选任务”,而是涉及 HR 效率、候选人体验、企业战略人才储备的三角关系。传统招聘模式下,这三角常常陷入 “HR 疲于奔命却难出成果、候选人等…...

Flash Attention原理

提出问题 Transformer 结构已成为自然语言处理和图像分类等应用中最常用的架构。尽管 Transformer 在规模上不断增大和加深,但处理更长上下文仍然是一个挑战,因为核心的自注意力模块在序列长度上具有二次方的时间和内存复杂度。这导致在处理长序列时速度变慢且内存需求巨大。…...

MSMQ 跨服务器读写队列的“消息队列系统的访问被拒绝”的解决方案

转:http://m.blog.csdn.net/blog/2000killer/8904852 在服务器上创建的Queue开发者的 机器只能写数据而不能读数据。.net给出的错误是“对消息队列系统的访问被拒绝”,也就是说拒绝访问队列没有相关权限,我给Everyone和 ANONYMOUS LOGON赋予全部权限都无法解决(正常情况下可…...

opencv学习记录1

img = cv2.imread(pic.jpg)#读图像 #封装函数 def cv_show(name,img):cv2.imshow(image,img)#显示图像cv2.waitKey(0)#显示时间cv2.destroyWindow()#读灰度图 img = cv2.imread(pic.jpg,cv2.IMREAD_GRAYSCALE) #保存 cv2.imwrite(name,img)#读视频 vc = cv2.VideoCapture(name)…...

kylin V10SP3安装mysql5.7.42

环境:OS:kylin V10SP3mysql:5.7.42查看系统glibc版本[root@localhost ~]# ldd --versionldd (GNU libc) 2.28Copyright (C) 2018 自由软件基金会。这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性或者适合某些特殊目的。由 Roland McGrath …...

MATLAB 仿真无线传感器网络(WSN)三大经典场景

一、统一参数区(建议先调这里) %% 0. 公共参数 clear; clc; close all; rng(2025) % 可重复 field = [0 100; 0 100]; % 100 m 100 m nNode = 200; % 节点数 R = 15; % 通信半径 /m E0 = 0.5; …...

9.05 DP 专题

Permutation Blackhole 按照过题人数顺序做题是这样的,如果要看难一点的建议向下 首先,不要读错题 QAQ 然后你现在发现每个位置只会在它被涂黑之前向最近放位置产生一次贡献,从 P 的角度思考是困难的,考虑从被涂黑的图的角度思考 你注意到我们每次涂完两个点之后,它们中间…...

MySQL主从复制 - 指南

MySQL主从复制 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14…...

阿里 Qoder 体验超预期,Repo Wiki 功能迎来全新升级

作者:沉默王二 大家好,我是二哥呀。 最近,阿里发布了一款名为 Qoder(/ˈkoʊdər/)的 Agentic 开发工具。我第一时间就去尝鲜了,其 Quest Mode 和 Repo Wiki 给我印象深刻。Quest Mode 主打一个 AI 自主研发,我们只需要把工程任务扔给他,Quest Mode 就会把模糊的需求翻…...

实用指南:ZooKeeper 的选举算法

实用指南:ZooKeeper 的选举算法pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; fon…...

JAVA获取keytab的Principal

依赖<dependency><groupId>org.apache.kerby</groupId><artifactId>kerb-client</artifactId><version>2.0.1</version></dependency> 代码执行Keytab keytab = Keytab.loadKeytab(new File("D:\\dl.keytab"));key…...

基于霍夫变换的MATLAB虹膜检测与分割实现

一、核心代码实现 function [iris_mask, pupil_center, iris_radius] = hough_iris_segmentation(img_path)% 读取图像并预处理img = imread(img_path);gray = rgb2gray(img);blurred = imgaussfilt(gray, 2); % 高斯滤波去噪denoised = medfilt2(blurred, [3 3]); % 中值滤波…...

Linux时间同步---NTP时间同步方案

1.方案背景: 在分布式系统或多服务器集群中,必须建立统一的时间同步机制。服务器间的时间不一致会破坏各类依赖时间交互逻辑,例如导致日志时序混乱、事务顺序错乱、证书验证失败等,从而引发一系列难以排查的不可预知故障。 2.NTP同步网络拓扑图: 3.同步方案 可提前咨询医…...

java预习

课前问题列表 1.什么样的方法应该用static修饰?不用static修饰的方法往往具有什么特性?Student的getName应该用static修饰吗?适合用 static 修饰的方法: 工具类方法(如Math.abs())、工厂方法、不需要访问实例变量 / 方法的方法、单例模式的获取实例方法等,这类方法通常与…...

B/S体系结构风格

三层B/S风格-概述 》浏览器/服务器(B/S)风格就是上述三层应用结构的一种实现方式,其具体结构为:浏览器/Web服务器/数据库服务器。 》B/S体系结构主要是利用不断成熟的WWW浏览技术,结合浏览的多种脚本语言,用通用浏览器就实现了原来需要复杂的专用软件才能实现的强大功能,…...

The 2024 CCPC Online Contest 7/12 L/B/K/D/J/E/C

Problem L. 网络预选赛 签到,直接模拟即可点击查看代码 #include<bits/stdc++.h> using namespace std; int main(){int n,m;cin>>n>>m;vector<string>a(n);for(int i=0;i<n;i++){cin>>a[i];}int sum=0;for(int i=0;i<n-1;i++){for(int j…...

在joule里面使用agent 功能

test: Dev: 1: structure 2: 本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究...