八股一https://blog.csdn.net/2401_82607598/article/details/159960625?fromshareblogdetailsharetypeblogdetailsharerId159960625sharereferPCsharesource2401_82607598sharefromfrom_linkhttps://blog.csdn.net/2401_82607598/article/details/160991619?fromshareblogdetailsharetypeblogdetailsharerId160991619sharereferPCsharesource2401_82607598sharefromfrom_link对STL容器的理解主要分成顺序容器关联容器又分无序容器和有序容器容器适配器其他容器看这个图Linux常用命令基本指令pwd显示当前目录路径ls查看文件和目录cd切换目录mkdir创建目录rmdir删除空目录touch创建空文件rm删除文件或目录mv重命名或移动文件/目录cp复制文件或目录文件查看命令cat查看文件内容head从文件头开始查看内容tail从文件尾部开始查看内容重定向指令覆盖写入追加写入时间日期指令datecal用户管理和组管理groupaddgroupdeluseradd新增用户userdel删除用户id查看用户信息su切换用户whoami查看当前用户文件权限chmod更改文件权限chown改变文件或目录的拥有者umask查看和修改新建时默认文件权限网络管理命令ifconfig查看网卡信息ping测试与某台主机的连通性curl用于发送HTTP请求host查询ip相关的域名netstat监测网络连接状态进程相关命令ps查看进程相关信息常用选项。。。ps -auxkill、killall停止杀死进程top实时显示进程的信息pstree以树的形式查看进程信息压缩和解压缩zip压缩文件或目录unzip解压gzip压缩单个文件gunzip解压gzip压缩的文件tar打包命令搜索查找find从指定目录下递归遍历各个子目录locate定位整个系统的文件路径grep文本搜索whichwhereis软件包管理yum listyum installyum remove还有一些零碎的vim编辑man查看文档helpshutdown关机被问到Linux查看CPU、GPUlscpu提供了CPU架构的详尽信息包括类型、核心数、每个核心的线程数、缓存大小cat /proc/cpuinfo查看/proc/cpuinfo文件Linux系统中这个文件详细了解到每个CPU核心的参数dmidecode提供硬件系统的详尽详细lspci查询所有PCI设备的标准命令配合grep可以过滤出显卡相关的信息lspci|grep -i vgaglxinfo获取OpenGL图形系统的详细信息包括GPU的制造商、型号https://blog.csdn.net/juluwangriyue/article/details/131957682?fromshareblogdetailsharetypeblogdetailsharerId131957682sharereferPCsharesource2401_82607598sharefromfrom_link互斥锁和读写锁的区别互斥锁互斥锁加锁失败后线程会释放CPU给其他线程。自旋锁加锁失败后线程会忙等待直到它拿到锁。读写锁由读锁和写锁两部分组成如果只读取共享资源用读锁加锁如果要修改共享资源用写锁加锁。读写锁适用于能明确区分读操作和写操作的场景。前面提到的互斥锁、自旋锁、读写锁都是属于悲观锁。悲观锁做事比较悲观它认为多线程同时修改共享资源的概率比较高于是很容易出现冲突所以访问共享资源前先要上锁。那相反的如果多线程同时修改共享资源的概率比较低就可以采用乐观锁。多数据的数据共享多线程数据共享核心原则保证线程安全控制可见性有序性原子性无锁方案原子变量atomic、线程局部存储TLS互斥同步主流方案mutex互斥锁、读写锁最常用搭配RAll智能锁lock_guard、unique_lock消息队列/生产者消费者解耦共享规避临界区设计层规避尽量少共享数据高并发内存池。线程局部存储threadlocalstorage简称TLS是一种存储机制它允许每个线程拥有自己的变量副本。每个线程可以无锁的获取自己的ThreadCache对象。C11之后可以直接用C 关键字thread_local去做声明就可以定义线程局部存储变量了这样可以跨平台。线程局部存储 TLS线程独有数据数据名义上全局实际每个线程一份副本线程间完全不共享天然安全。#include iostream #include thread using namespace std; thread_local int g_num 0; // 每个线程独立副本 void func(int id) { g_num id; cout 线程 id num g_num endl; } int main() { thread t1(func, 1); thread t2(func, 2); t1.join(); t2.join(); return 0; }线程局部存储配合单例模式和智能指针。。。结合C多线程场景分核心方案、选型、代码示例、避坑要点按面试/工程实用角度整理聚焦多线程共享数据全套解法。一、总体思路多线程共享数据核心原则保证线程安全 控制可见性、有序性、原子性主要分四大类方案1. 无锁方案原子变量、线程局部存储2. 互斥同步互斥锁、读写锁最常用3. 消息队列/生产者消费者解耦共享规避临界区4. 设计层面规避尽量少共享数据二、方案详解 适用场景 代码1. 优先方案减少共享最佳实践能不共享就不共享从根源解决线程安全问题。• 每个线程使用私有局部变量不对外暴露• 任务拆分数据随任务走而非全局共享• 函数传参尽量值传递/右值引用少用裸指针/全局引用面试话术多线程设计第一准则数据私有化弱化共享。2. 线程局部存储 TLS线程独有数据数据名义上全局实际每个线程一份副本线程间完全不共享天然安全。C 关键字thread_local示例#include iostream #include thread using namespace std; thread_local int g_num 0; // 每个线程独立副本 void func(int id) { g_num id; cout 线程 id num g_num endl; } int main() { thread t1(func, 1); thread t2(func, 2); t1.join(); t2.join(); return 0; }适用场景• 每个线程需要独立的全局状态、计数器、缓存• 完全不需要线程间数据交互特点• 无线程竞争、无锁、性能极高• 数据不互通无法用来做多线程数据交互3. 轻量级原子变量 std::atomic简单数值共享针对单个整型、指针、布尔值共享无锁依靠CPU原子指令实现线程安全。无需加锁开销远低于互斥锁。常用类型std::atomicint / std::atomicbool / std::atomiclong 等示例多线程计数#include iostream #include thread #include atomic using namespace std; atomicint g_cnt 0; // 原子变量线程安全 void add() { for (int i 0; i 10000; i) { g_cnt; // 自增原子操作 } } int main() { thread t1(add); thread t2(add); t1.join(); t2.join(); cout 总数 g_cnt endl; // 结果正确 20000 return 0; }适用 限制✅ 适用计数器、状态标志、开关、简单数值同步❌ 不适用复合操作、结构体、对象、多条语句如 if 赋值 组合依然有竞态补充内存序默认 std::memory_order_seq_cst顺序一致追求极致性能可放宽内存序面试了解即可。4. 主流方案互斥锁 mutex复杂共享数据多个线程读写对象、容器、多变量组合使用互斥锁保护临界区同一时刻仅一个线程访问。搭配 RAII 智能锁 std::lock_guard / std::unique_lock避免漏解锁。基础示例共享容器#include iostream #include thread #include mutex #include vector using namespace std; vectorint g_vec; mutex g_mtx; void write() { for (int i 0; i 100; i) { // RAII 上锁出作用域自动解锁 lock_guardmutex lock(g_mtx); g_vec.push_back(i); } } void read() { while (true) { lock_guardmutex lock(g_mtx); if (!g_vec.empty()) { cout g_vec.back() ; break; } } } int main() { thread t1(write); thread t2(read); t1.join(); t2.join(); return 0; }关键要点1. 临界区尽量短小只把读写共享数据的代码加锁无关逻辑移出2. 禁止锁内耗时操作IO、sleep、网络严重阻塞并发3. 避免死锁多锁保持固定加锁顺序、不嵌套锁5. 读多写少专用读写锁 shared_mutex承接上一轮问答读共享、写独占高并发读场景大幅提升性能。示例#include iostream #include thread #include shared_mutex #include string using namespace std; string g_config default; shared_mutex g_rw_mtx; // 读线程共享锁多线程同时读 void read_config(int id) { shared_lockshared_mutex lock(g_rw_mtx); cout 读线程 id : g_config endl; } // 写线程独占锁排他所有读写 void write_config() { unique_lockshared_mutex lock(g_rw_mtx); g_config new setting; cout 写线程更新配置 endl; } int main() { thread t1(read_config, 1); thread t2(read_config, 2); thread t3(write_config); t1.join(); t2.join(); t3.join(); return 0; }适用场景• 配置数据、全局缓存、静态报表、查询远多于修改6. 解耦方案生产者/消费者 阻塞队列不直接共享全局数据用线程安全队列中转数据线程间通过队列通信彻底隔离临界区。工程中高频用于日志、任务队列、数据转发。简易线程安全队列#include iostream #include thread #include mutex #include queue #include condition_variable using namespace std; templatetypename T class SafeQueue { private: queueT q; mutable mutex mtx; condition_variable cv; public: void push(T val) { lock_guardmutex lock(mtx); q.push(val); cv.notify_one(); // 唤醒等待线程 } bool pop(T val) { unique_lockmutex lock(mtx); // 队空则等待 cv.wait(lock, [this](){ return !q.empty(); }); val q.front(); q.pop(); return true; } }; SafeQueueint data_queue; // 生产者 void producer() { for (int i 1; i 5; i) { data_queue.push(i); } } // 消费者 void consumer() { int val; while (data_queue.pop(val)) { cout 消费 val endl; } } int main() { thread t1(producer); thread t2(consumer); t1.join(); t2.join(); return 0; }优势• 线程解耦读写分离逻辑清晰• 配合条件变量实现阻塞等待无忙等浪费CPU三、方案选型速查表面试直接背场景 推荐方案 优点完全不需要数据互通、每个线程独立数据 thread_local 无锁、性能最高单个数值/布尔、简单计数/状态 std::atomic 无锁、轻量普通读写、数据结构/对象共享、读写均衡 std::mutex 互斥锁 简单通用、不易出错读多写少配置、缓存 std::shared_mutex 读写锁 高并发读性能好线程间数据流转、任务分发、日志 阻塞队列(队列互斥锁条件变量) 解耦、架构清晰四、通用避坑要点面试高频考点1. 竞态条件多条语句操作共享变量必须加锁原子变量只保护单条原子操作。2. 临界区最小化锁范围越小并发越高。3. 死锁防范多锁顺序一致、不嵌套锁、不在锁内调用外部函数。4. 可见性问题多线程共享变量不要依赖编译器优化优先用锁/原子保证内存可见。5. 拒绝裸全局变量尽量封装成类把锁和数据绑定在一起封装线程安全类。6. 锁粒度选择粗粒度锁一把锁保护所有数据简单但并发低细粒度锁多分锁并发高但易死锁。五、面试一句话总结1. 能不共享就不共享优先 thread_local 私有化数据2. 简单数值用原子变量无锁实现3. 常规对象/容器共享用互斥锁4. 读多写少场景改用读写锁提升并发5. 线程间数据流转用阻塞队列解耦是工程最优实践。C新标准新特性后面补充autonullptrfor语法糖列表初始化overridedeletedefault关键字匿名函数右值引用线程类STL标准模板库左值和右值通俗话讲了。。move语句左值右值都是表示数据的表达式。左值具有地址可以出现在赋值号左侧可以取地址变量、对象、数组元素都是左值。。右值通常没有地址存储在寄存器或临时内存中不能出现在赋值号的左侧不能取地址除非是绑定到const左值引用中字面量、表达式计算结果都是右值。左值表示一个占据内存中可识别位置的一个对象如变量名或解引用的指针我们可以获取它的地址可以给他赋值。右值如字面常量、表达式返回值、函数返回值。不能对变量或表达式取地址左值可以出现赋值符号的左边右值不能出现在赋值符号左边。右值可以出现在赋值符号的右边但不能在左边右值不能取地址。move用于将一个对象的资源移动到另一个对象而不是拷贝资源。指针和智能指针指针是什么git分支相关三次握手和四次挥手总结成通俗的话python里面装饰器