什么是线程同步?
想象一下超市收银台:如果所有顾客(线程)同时挤向同一个收银台(共享资源),场面会一片混乱。线程同步就是给顾客们发"排队号码牌",确保:
- 有序访问:每次只处理一个顾客
- 协调工作:收银员(cpu)高效服务
- 避免冲突:防止算错账(数据错误)
linux提供5种"排队机制"解决多线程协作问题:
一、互斥锁(单人洗手间规则)
#include <pthread.h>
// 创建锁(相当于洗手间的"有人/无人"标识)
pthread_mutex_t lock = pthread_mutex_initializer;
void* thread_task(void* arg) {
// 尝试进入(如果里面有人就排队等待)
pthread_mutex_lock(&lock);
/* 临界区开始(你的"私人时间") */
printf("thread %d using resource\n", *(int*)arg);
sleep(1); // 模拟耗时操作
/* 临界区结束 */
// 开门出来(让下一位使用)
pthread_mutex_unlock(&lock);
return null;
}
适用场景:
- 文件写入操作
- 银行账户余额修改
- 任何需要"独享"资源的场景
特点:
- 简单易用
- 过度使用会降低并发性能
二、条件变量(咖啡厅取餐系统)
pthread_cond_t order_ready = pthread_cond_initializer;
pthread_mutex_t counter_lock = pthread_mutex_initializer;
int order_number = 0;
// 顾客线程(等待取餐)
void* customer(void* arg) {
pthread_mutex_lock(&counter_lock);
while(order_number == 0) { // 必须用while循环检查
pthread_cond_wait(&order_ready, &counter_lock); // 放下锁等待通知
}
printf("got order %d!\n", order_number);
pthread_mutex_unlock(&counter_lock);
return null;
}
// 厨师线程(通知取餐)
void* chef(void* arg) {
sleep(2); // 模拟做饭时间
pthread_mutex_lock(&counter_lock);
order_number = 123;
pthread_cond_signal(&order_ready); // 叫号通知顾客
pthread_mutex_unlock(&counter_lock);
return null;
}
工作流程:
- 顾客:锁定柜台 → 检查订单 → 等待叫号
- 厨师:完成订单 → 锁定柜台 → 更新订单 → 发送通知
- 顾客:被唤醒 → 重新检查 → 取餐
适用场景:
- 生产者-消费者模型(如消息队列)
- 线程间任务协调
三、自旋锁(抢车位)
pthread_spinlock_t parking_lock;
// 初始化锁(停车场入口)
pthread_spin_init(&parking_lock, pthread_process_private);
void* driver(void* arg) {
// 开车绕圈找空位(cpu忙等待)
pthread_spin_lock(&parking_lock);
/* 停车成功(临界区) */
printf("car %d parked\n", *(int*)arg);
// 开走释放车位
pthread_spin_unlock(&parking_lock);
return null;
}
适用场景:
- 极短操作(<0.1毫秒)
- 内核开发
- 实时系统
注意事项:
- 会浪费cpu资源
- 比互斥锁响应更快
锁类型对比表:
| 场景 | 推荐锁类型 | 类比 |
|---|---|---|
| 短时间独占操作 | 自旋锁 | 快速便利店购物 |
| 长时间独占操作 | 互斥锁 | 餐厅包间用餐 |
| 多读少写 | 读写锁 | 图书馆 |
| 线程组协调 | 屏障 | 旅行团集合 |
| 事件通知 | 条件变量 | 咖啡厅叫号系统 |
到此这篇关于linux实现线程同步的五种方式的文章就介绍到这了,更多相关linux线程同步内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论