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

Linux 之 【多线程】(STL、智能指针与线程安全、读者写者问题)

目录

1.STL、智能指针与线程安全

STL容器默认不是线程安全的

智能指针线程安全

2.读者写者问题

背景

读写锁核心特性

321原则

优先级策略

POSIX读写锁接口

读写锁示例

设置写者优先示例


1.STL、智能指针与线程安全

STL容器默认不是线程安全的

多线程环境下需要调用者自行保证线程安全
常见方案:使用外部锁(如std::mutex)保护容器操作

智能指针线程安全

1.unique_ptr(独享所有权)

  • 线程安全特性:不涉及线程安全问题

  • 原因:只在当前代码块范围内生效,独占资源所有权,不存在多个线程共享的情况

2. shared_ptr(共享所有权)

两部分需要区分对待

组成部分线程安全性说明
引用计数线程安全标准库基于原子操作(CAS)实现,保证高效原子操作
管理的资源不保证安全智能指针只负责管理资源生命周期,不保护资源内容的并发访问

关键理解

  • 引用计数的增减是原子操作,多个线程同时操作shared_ptr不会导致计数错乱

  • 但通过shared_ptr访问的资源对象本身,需要调用者自行加锁保护

2.读者写者问题

  • 背景

多读少写场景:某些公共数据修改机会少,但读取查找操作频繁且耗时。传统互斥锁会严重降低并发效率,需要专门机制处理

  • 读写锁核心特性

特性说明
写独占写者加锁时,其他读者和写者都不能访问
读共享多个读者可以同时加锁读取数据
优先级可设置读者优先或写者优先
  • 321原则

维度内容说明
3种关系写写互斥多个写者不能同时写
写读互斥、同步写和读不能同时进行,且需数据同步
读读共享多个读者可以同时读
2种角色读者、写者两类线程操作数据
1个交易场所共享数据数据交换的内存区域
  • 优先级策略

策略特点问题适用场景
读者优先(默认)读者持续进入时,写者被阻塞写者可能饥饿读极多、写可延迟
写者优先写者到达后阻塞后续读者读者可能饥饿写操作需及时响应

读者优先策略下,只要存在任何读者正在读取数据,后续到达的读者可以立即获得读锁继续读取,而写者必须等待所有读者释放锁后才能写入。这种策略适合读操作极其频繁、写操作可以延迟的场景,但可能导致写者饥饿——当读者持续不断地到来时,写者可能永远无法获得写锁

写者优先策略下,一旦有写者到达并等待写锁,后续新到达的读者将被阻塞,不能插队读取,直到等待的写者完成写入操作。这种策略确保写操作能及时执行,适合需要数据及时更新的场景,但可能造成读者饥饿——如果写者频繁出现,读者可能长时间无法获取读锁。

  • POSIX读写锁接口

// 设置优先级 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref); /* pref取值: PTHREAD_RWLOCK_PREFER_READER_NP - 读者优先(默认) PTHREAD_RWLOCK_PREFER_WRITER_NP - 写者优先(有BUG,实际同读者优先) PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP - 写者优先,写者不可递归 */ // 初始化和销毁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); // 加锁和解锁 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); // 读锁 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); // 写锁 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); // 解锁
  • 读写锁示例

#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> // 共享数据 int shared_data = 0; // 读写锁 pthread_rwlock_t rwlock; // 读者线程 void* reader(void* arg) { int id = *(int*)arg; while (1) { // 加读锁 pthread_rwlock_rdlock(&rwlock); printf("读者 %d 读取数据: %d\n", id, shared_data); // 模拟读取耗时 usleep(100000); pthread_rwlock_unlock(&rwlock); // 间隔一段时间再读 usleep(500000); } return NULL; } // 写者线程 void* writer(void* arg) { int id = *(int*)arg; while (1) { // 加写锁 pthread_rwlock_wrlock(&rwlock); shared_data++; printf("写者 %d 修改数据为: %d\n", id, shared_data); // 模拟写入耗时 usleep(200000); pthread_rwlock_unlock(&rwlock); // 间隔一段时间再写 usleep(2000000); } return NULL; } int main() { // 初始化读写锁(默认读者优先) pthread_rwlock_init(&rwlock, NULL); pthread_t readers[3], writers[2]; int reader_ids[3] = {1, 2, 3}; int writer_ids[2] = {1, 2}; // 创建3个读者线程 for (int i = 0; i < 3; i++) { pthread_create(&readers[i], NULL, reader, &reader_ids[i]); } // 创建2个写者线程 for (int i = 0; i < 2; i++) { pthread_create(&writers[i], NULL, writer, &writer_ids[i]); } // 运行一段时间后退出(示例用sleep) sleep(10); // 销毁读写锁 pthread_rwlock_destroy(&rwlock); return 0; }
  • 设置写者优先示例

#include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_rwlock_t rwlock; int shared_counter = 0; void* reader_func(void* arg) { int id = *(int*)arg; for (int i = 0; i < 5; i++) { pthread_rwlock_rdlock(&rwlock); printf("读者 %d 读取: %d\n", id, shared_counter); usleep(50000); // 模拟读取 pthread_rwlock_unlock(&rwlock); usleep(100000); } return NULL; } void* writer_func(void* arg) { int id = *(int*)arg; for (int i = 0; i < 3; i++) { pthread_rwlock_wrlock(&rwlock); shared_counter++; printf("写者 %d 写入: %d\n", id, shared_counter); usleep(100000); // 模拟写入 pthread_rwlock_unlock(&rwlock); usleep(500000); } return NULL; } int main() { // 设置写者优先 pthread_rwlockattr_t attr; pthread_rwlockattr_init(&attr); pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); pthread_rwlock_init(&rwlock, &attr); pthread_t readers[5], writers[2]; int reader_ids[5] = {1, 2, 3, 4, 5}; int writer_ids[2] = {1, 2}; // 创建线程 for (int i = 0; i < 5; i++) { pthread_create(&readers[i], NULL, reader_func, &reader_ids[i]); } for (int i = 0; i < 2; i++) { pthread_create(&writers[i], NULL, writer_func, &writer_ids[i]); } // 等待线程结束 for (int i = 0; i < 5; i++) { pthread_join(readers[i], NULL); } for (int i = 0; i < 2; i++) { pthread_join(writers[i], NULL); } pthread_rwlock_destroy(&rwlock); pthread_rwlockattr_destroy(&attr); return 0; }
http://www.jsqmd.com/news/384618/

相关文章:

  • 照着用就行:专科生专属降AI工具 —— 千笔·降AI率助手
  • 2025年度口碑!全球用户点赞的碳酸镁直销厂家推荐,做得好的碳酸镁源头厂家口碑排行博仕佶镁专注产品质量 - 品牌推荐师
  • 【Python】常用的语法糖
  • C++11 之 【线程库】(condition_variable、atomic、线程交替打印奇偶数、谓词、线程总结)
  • 2026年靠谱的谈判离婚律师/光谷离婚律师专业推荐事务所 - 行业平台推荐
  • 2026年质量好的外置式余热锅炉/内置式烧结余热锅炉行业内口碑厂家推荐 - 行业平台推荐
  • OpenClaw在Win 环境下成功部署集成飞书
  • 2026年口碑好的苏州空气过滤器/漆雾过滤器用户口碑认可厂家 - 行业平台推荐
  • 2026年质量好的发电机/潍柴发电机厂家实力揭秘 - 行业平台推荐
  • Linux 应用层研发入门(十三)| 字符的编码方式
  • 2026年质量好的柴油发电机/奔驰柴油发电机厂家怎么挑 - 行业平台推荐
  • 2026年口碑好的威海劳动仲裁律师/威海房产律师品牌推荐事务所 - 行业平台推荐
  • 2026年评价高的福建玄金瓦/金虹科玄金瓦哪家好销售厂家推荐 - 行业平台推荐
  • 不踩雷!千笔AI,遥遥领先的降AI率软件
  • 一篇搞定全流程AI论文网站 千笔写作工具 VS 灵感风暴AI,专科生首选
  • 基于卷积神经网络-双向长短时记忆网络结合SE注意力机制的数据回归预测(CNN-BiLSTM-SE)
  • 2026别错过!AI论文写作软件 千笔·专业论文写作工具 VS PaperRed,专为本科生打造!
  • 2026年靠谱的广州肉类冷库设备/高温保鲜冷库设备工厂直供推荐哪家专业 - 行业平台推荐
  • 2026年知名的彩石瓦厂家/福建彩石瓦直销厂家采购指南如何选 - 行业平台推荐
  • 2026年靠谱的天车龙门五轴加工中心/摆头五轴加工中心哪家靠谱制造厂家推荐 - 行业平台推荐
  • 2026年热门的植提设备分离设备/植提设备干燥设备源头厂家采购指南怎么选(畅销) - 行业平台推荐
  • 一文讲透|AI论文平台 千笔·专业论文写作工具 VS speedai,本科生专属神器!
  • 2026年比较好的智能控温冷库变频机组/广州冷库变频机组热门品牌推荐口碑排行 - 行业平台推荐
  • 2026年知名的激光焊接机/手持式激光焊接机高口碑品牌参考选哪家 - 行业平台推荐
  • 2026年靠谱的飞机小桌板/动车小桌板直销厂家价格参考怎么选 - 行业平台推荐
  • 2026年靠谱的托底轨家具功能五金/钢珠轨家具功能五金厂家推荐哪家好(高评价) - 行业平台推荐
  • 2026年热门的轻薄塑身衣/束腰塑身衣口碑排行热门品牌推荐(实用) - 行业平台推荐
  • 2026年酒精厌氧絮状菌种选哪家?实力厂家选择指南,市面上有名的酒精厌氧絮状菌种公司精选实力品牌榜单发布 - 品牌推荐师
  • FastDDS是什么?如何进行源码编译?