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

Linux:读写锁与自旋锁

一、读写锁

1. 什么是读者写者问题?

读者写者模型是一种多线程同步策略,适用于高频读、低频写的场景。
比如博客文章:作者(写者)发布后很少修改,而读者(读者)频繁访问。
在这种场景下,使用读写锁可以比互斥锁减少很多锁冲突。

2. 读者写者问题的"321"原则

  • 3种关系

    • 读者与读者:互斥(但实际允许多个读者同时读)
    • 读者与写者:互斥和同步(读时不能写,写时不能读)
    • 写者与写者:互斥(不能同时写)
  • 2种角色:读者和写者

  • 1个交易场所:共享内存空间(如黑板、缓冲区)

3. 读写锁 vs 生产者消费者模型

为什么写者之间需要互斥,而消费者之间也需要互斥?关键区别在于:

  • 消费者会取走数据,修改缓冲区
  • 写者只修改数据,不取走,但修改操作仍需互斥保护

4. 读写锁实现原理

// 伪代码实现uint32_treader_count=0;lock_t count_lock;// 保护读者计数器的锁lock_t writer_lock;// 写者锁// 读者lock(count_lock);if(reader_count==0)lock(writer_lock);// 第一个读者阻止写者++reader_count;unlock(count_lock);// 执行读操作lock(count_lock);--reader_count;if(reader_count==0)unlock(writer_lock);// 最后一个读者唤醒写者unlock(count_lock);// 写者lock(writer_lock);// 执行写操作unlock(writer_lock);
当前锁状态读锁请求写锁请求
无锁✅ 可以✅ 可以
读锁✅ 可以❌ 阻塞
写锁❌ 阻塞❌ 阻塞

5. POSIX 线程库接口

#include<pthread.h>// 初始化读写锁intpthread_rwlock_init(pthread_rwlock_t*restrict rwlock,constpthread_rwlockattr_t*restrict attr);// 销毁读写锁intpthread_rwlock_destroy(pthread_rwlock_t*rwlock);// 读者加锁intpthread_rwlock_rdlock(pthread_rwlock_t*rwlock);// 写者加锁intpthread_rwlock_wrlock(pthread_rwlock_t*rwlock);// 解锁intpthread_rwlock_unlock(pthread_rwlock_t*rwlock);

6. 完整示例代码

#include<iostream>#include<pthread.h>#include<unistd.h>#include<vector>#include<cstdlib>#include<ctime>intshared_data=0;pthread_rwlock_t rwlock;void*Reader(void*arg){intnumber=*(int*)arg;while(true){pthread_rwlock_rdlock(&rwlock);std::cout<<"读者-"<<number<<" 读取数据: "<<shared_data<<std::endl;sleep(1);pthread_rwlock_unlock(&rwlock);}delete(int*)arg;returnNULL;}void*Writer(void*arg){intnumber=*(int*)arg;while(true){pthread_rwlock_wrlock(&rwlock);shared_data=rand()%100;std::cout<<"写者-"<<number<<" 写入数据: "<<shared_data<<std::endl;sleep(2);pthread_rwlock_unlock(&rwlock);}delete(int*)arg;returnNULL;}intmain(){srand(time(nullptr)^getpid());pthread_rwlock_init(&rwlock,NULL);constintreader_num=2;constintwriter_num=2;constinttotal=reader_num+writer_num;pthread_t threads[total];// 创建读者线程for(inti=0;i<reader_num;++i){int*id=newint(i);pthread_create(&threads[i],NULL,Reader,id);}// 创建写者线程for(inti=reader_num;i<total;++i){int*id=newint(i-reader_num);pthread_create(&threads[i],NULL,Writer,id);}for(inti=0;i<total;++i){pthread_join(threads[i],NULL);}pthread_rwlock_destroy(&rwlock);return0;}

7. 写者饥饿问题

读写锁允许多个读者同时读,可能导致读者连续进入,写者长期无法获得锁,造成写者饥饿。

8. 读者优先 vs 写者优先

策略特点问题
读者优先读者优先获得锁,写者等待所有读者完成写者饥饿
写者优先写者优先获得锁,读者等待所有写者完成读者饥饿

注:读写锁默认采用读者优先策略


二、自旋锁

1. 什么是自旋锁?

自旋锁是一种多线程互斥机制,与互斥锁的区别在于锁获取失败时的行为

  • 互斥锁:失败后线程阻塞,上下文切换
  • 自旋锁:失败后线程循环检查,忙等待

2. 适用场景

锁类型适用场景特点
互斥锁临界区执行时间长避免CPU空转
自旋锁临界区执行时间短避免上下文切换开销

3. 实现原理

// 原子操作实现atomic_flag lock=ATOMIC_FLAG_INIT;// 加锁while(atomic_flag_test_and_set(&lock)){// 自旋等待}// 临界区// 解锁atomic_flag_clear(&lock);

4. POSIX 自旋锁接口

#include<pthread.h>// 初始化自旋锁intpthread_spin_init(pthread_spinlock_t*lock,intpshared);// 销毁自旋锁intpthread_spin_destroy(pthread_spinlock_t*lock);// 加锁intpthread_spin_lock(pthread_spinlock_t*lock);intpthread_spin_trylock(pthread_spinlock_t*lock);// 解锁intpthread_spin_unlock(pthread_spinlock_t*lock);

5. 自旋锁的优缺点

优点
  • ✅ 避免线程阻塞/唤醒的上下文切换开销
  • ✅ 适合短时间锁持有场景
缺点
  • ❌ 浪费CPU资源(空转)
  • ❌ 可能导致活锁(多个线程相互等待)
  • ❌ 可能加剧系统负载

三、总结对比

特性读写锁自旋锁
主要用途读多写少场景短临界区保护
锁失败行为线程阻塞CPU空转
并发级别多读单写单线程持有
适用场景高频读、低频写临界区执行时间极短
主要问题写者饥饿CPU浪费、活锁
http://www.jsqmd.com/news/461319/

相关文章:

  • 多无人机动态避障路径规划研究:基于遗传算法GA的复杂三维山体环境下多无人机动态避障路径规划研究(可以自定义无人机数量及起始点),MATLAB代码
  • OpenClaw 记忆系统终极指南:从“金鱼记忆”到永不失忆(MemOS 插件 + 4 大社区实战方法)
  • 杰理之1. 启动解码和关闭解码【篇】
  • eNSP启动报:43
  • 杰理之Page Scan连接扫描【篇】
  • 告别边界噩梦:LeetCode Hot 100 高频漏等号场景全解析
  • GEO优化发布测试22:35:07
  • 最小二乘问题详解15:束平差原理与基础实现
  • openclaw在windows和mac上的安装以及AI技术中的几个关键概念,包括大模型、MCP协议、Skills、智能体和OpenClaw。
  • 基于 SpringBoot 和 Vue 的高效社团管理系统项目分享
  • 测试文章01
  • 实测了上百个AI工具,能留在我2026年收藏夹里的只有这47个(全场景覆盖)
  • Spring中有哪些地方用到了反射
  • 飞牛NAS重启掉阵列?真相是SATA节能惹的祸!两步彻底解决ALPM掉盘与“11/12 failed”误报
  • OpenClaw 重置恢复不失忆的保姆级恢复步骤(附新版本功能介绍)
  • 4-29找出不是两个数组共有的元素
  • 超详细:LeetCode Hot 100 高频漏等号场景全总结
  • 基于手机端的问卷调查小程序设计与实现
  • 乡村特产选购助手项目介绍
  • 新郑市靠谱的门窗门店有哪些
  • 迅雷链接解析工具_迅雷网盘解析
  • DeepSeek降AI指令vs专业降AI工具,哪个效果更好?实测揭晓
  • HJ123 预知
  • 医药企业如何系统性把握政策法规?一套系统解决信息碎片化难题
  • 舒展解僵硬,松弛养身心|武汉瑜伽伸展课程,禧悦解锁全身舒缓新体验 - 冠顶工业设备
  • 从BERT到ChatGPT:一文精通文本分类的N种姿势(附代码)
  • Europe can only be Europe.
  • OpenClaw的数据是存在哪里的?会上传到云端吗?深度解析
  • 2026年高端进口板材品牌决策咨询评测报告 - 品牌推荐
  • 代码随想录算法训练营第四十二天|52. 携带研究材料、518. 零钱兑换 II、377. 组合总和 Ⅳ、57. 爬楼梯(进阶)