资讯详情

Linux 学习笔记(三十六):并发进阶——读写锁 vs 自旋锁,到底怎么选?

📅 2026/10/29 2:06:57 | 华诺云谱 👁 阅读
Linux 学习笔记(三十六):并发进阶——读写锁 vs 自旋锁,到底怎么选?
核心结论TL;DR选型口诀多读少写选读写锁极短临界区多核选自旋锁复杂逻辑选互斥锁Mutex。读写锁三大铁律读读共享、读写互斥、写写互斥。自旋锁致命缺点如果锁被占用时间较长线程一直原地“忙等待自旋”会白白把 CPU 跑满浪费算力。饥饿问题读写锁默认策略下如果读者源源不断写者可能会被“饿死”长时间抢不到锁。一、 互斥锁的局限性传统的互斥锁Mutex非常霸道无论你是读取数据还是修改数据只要有线程加锁其他线程全部阻塞。但在实际开发中往往是“多读少写”的场景。如果读操作也互斥系统的并发性能将大打折扣。二、 读写锁Reader-Writer Lock读写锁专门针对多读少写场景设计遵循三大核心规则读读共享多个线程可以同时持有读锁。读写互斥写操作独占此时不允许任何读操作。写写互斥多个写线程之间必须互斥。核心 APIpthread_rwlock_rdlock()加读锁。pthread_rwlock_wrlock()加写锁。pthread_rwlock_unlock()解锁。(插入 rwlock_test.cc 代码)#include iostream #include pthread.h #include unistd.h int shared_data 0; pthread_rwlock_t rwlock; void* Reader(void* arg) { long id (long)arg; while (true) { pthread_rwlock_rdlock(rwlock); // 加读锁 std::cout 读者- id 正在读取数据: shared_data std::endl; sleep(1); pthread_rwlock_unlock(rwlock); // 解锁 } return nullptr; } void* Writer(void* arg) { long id (long)arg; while (true) { pthread_rwlock_wrlock(rwlock); // 加写锁 shared_data; std::cout 写者- id 正在写入数据: shared_data std::endl; sleep(1); pthread_rwlock_unlock(rwlock); sleep(1); } return nullptr; }三、 自旋锁Spinlock自旋锁与 Mutex 的最大区别在于“等待”的方式Mutex发现锁被占用会让线程进入睡眠状态阻塞态让出 CPU。醒来时需要上下文切换开销大。Spinlock发现锁被占用会开启死循环原地自旋忙等待不放弃 CPU。(插入 spinlock_test.cc 核心代码)pthread_spinlock_t spinlock; // 自旋锁 void* route(void* arg) { while (true) { pthread_spin_lock(spinlock); // 加自旋锁 if (ticket 0) { // 极短的操作 ticket--; } else { pthread_spin_unlock(spinlock); break; } pthread_spin_unlock(spinlock); } }四、 面试必考如何避坑与选型自旋锁的坑由于是在原地死循环如果临界区代码很长其他线程会白白消耗大量 CPU 资源在单核 CPU 上尤为致命因为自旋的线程占着 CPU拿到锁的线程根本没法运行。读写锁的“写者饥饿”在默认读者优先的策略下如果一直有新的读者进来写者可能永远无法获得写锁。可以通过设置PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP属性让写者优先。选型总结读操作多、写操作少 →→读写锁。临界区只有几条指令且是多核 CPU →→自旋锁。临界区长、逻辑复杂 →→互斥锁 (Mutex)。自我实战操作咱们来写一段代码用读写锁模拟“2 个读者2 个写者”同时访问一个共享数据。cd ~/linux_study mkdir rw_spin_test cd rw_spin_test实战 1读写锁测试vim rwlock_test.cc(输入以下代码)#include iostream #include pthread.h #include unistd.h int shared_data 0; // 共享数据 pthread_rwlock_t rwlock; // 读写锁 // 读者线程 void* Reader(void* arg) { long id (long)arg; while (true) { pthread_rwlock_rdlock(rwlock); // 加读锁 std::cout 读者- id 正在读取数据: shared_data std::endl; sleep(1); // 模拟读取耗时 pthread_rwlock_unlock(rwlock); // 解锁 // sleep(1); // 打开这个注释写者会饿死 } return nullptr; } // 写者线程 void* Writer(void* arg) { long id (long)arg; while (true) { pthread_rwlock_wrlock(rwlock); // 加写锁 shared_data; std::cout 写者- id 正在写入数据: shared_data std::endl; sleep(1); // 模拟写入耗时 pthread_rwlock_unlock(rwlock); // 解锁 sleep(1); // 写者给读者留点机会 } return nullptr; } int main() { pthread_rwlock_init(rwlock, nullptr); pthread_t r1, r2, w1, w2; pthread_create(r1, nullptr, Reader, (void*)1); pthread_create(r2, nullptr, Reader, (void*)2); pthread_create(w1, nullptr, Writer, (void*)1); pthread_create(w2, nullptr, Writer, (void*)2); pthread_join(r1, nullptr); pthread_join(r2, nullptr); pthread_join(w1, nullptr); pthread_join(w2, nullptr); pthread_rwlock_destroy(rwlock); return 0; }编译运行g rwlock_test.cc -o rwlock_test -lpthread ./rwlock_test现象你会看到“读者-1”和“读者-2”经常一起打印读读共享但当“写者”打印时两个读者必定是停住的读写互斥。实战 2自旋锁测试(注意自旋锁在单核虚拟机上测试效果不明显但代码必须要会写)vim spinlock_test.cc(输入以下代码)#include iostream #include pthread.h #include unistd.h int ticket 1000; pthread_spinlock_t spinlock; // 自旋锁 void* route(void* arg) { long id (long)arg; while (true) { pthread_spin_lock(spinlock); // 加自旋锁 if (ticket 0) { usleep(100); // 模拟极短的操作 printf(线程-%ld 卖出票: %d\n, id, ticket); ticket--; } else { pthread_spin_unlock(spinlock); break; } pthread_spin_unlock(spinlock); // 解锁 } return nullptr; } int main() { pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE); pthread_t t1, t2, t3; pthread_create(t1, nullptr, route, (void*)1); pthread_create(t2, nullptr, route, (void*)2); pthread_create(t3, nullptr, route, (void*)3); pthread_join(t1, nullptr); pthread_join(t2, nullptr); pthread_join(t3, nullptr); pthread_spin_destroy(spinlock); return 0; }(编译运行g spinlock_test.cc -o spinlock_test -lpthread ./spinlock_test)
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑