携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
同步 (Synchronization)
两个或两个以上随时间变化的量在变化过程中保持一定的相对关系
- iPhone/iCloud 同步 (手机 vs 电脑 vs 云端)
- 变速箱同步器 (合并快慢速齿轮)
- 同步电机 (转子与磁场速度一致)
- 同步电路 (所有触发器在边沿同时触发)
异步 (Asynchronous) = 不同步
- 上述很多例子都有异步版本 (异步电机、异步并发程序中的同步
并发程序的步调很难保持 “完全一致”
线程同步:
在某个时间点共同达到互相已知的状态
再次把线程想象成我们自己
- NPY:等我洗个头就出门/等我打完这局游戏就来
- 舍友:等我修好这个 bug 就吃饭
- 导师:等我出差回来就讨论这个课题
- jyy: 等我成为卷王就躺平
-
- “先到先等”电路、异步线程)
线程同步就是两个线程约定好一个时间达到互相知道的状态。
生产者-消费者问题:
99% 的实际并发问题都可以用生产者-消费者解决。
void Tproduce() { while (1) printf("("); } void Tconsume() { while (1) printf(")"); }
在 printf 前后增加代码,使得打印的括号序列满足
- 一定是某个合法括号序列的前缀
- 括号嵌套的深度不超过n
- 当n等于3时
- ((())())((( 合法
- (((()))), (())) 不合法
- 同步
-
- 等到有空位再打印左括号
- 等到能配对时再打印右括号
生产者-消费者问题:分析
为什么叫 “生产者-消费者” 而不是 “括号问题”?
- 左括号:生产资源 (任务)、放入队列
- 右括号:从队列取出资源 (任务) 执行
能否用互斥锁实现括号问题?
- 左括号:嵌套深度 (队列) 不足 n 时才能打印
- 右括号:嵌套深度 (队列) >1 时才能打印
-
- 当然是等到满足条件时再打印了:pc.c
-
- 用互斥锁保持条件成立
#include "thread.h" #include "thread-sync.h" int n, count = 0; mutex_t lk = MUTEX_INIT(); void Tproduce() {//老师(生产者) while (1) { retry: mutex_lock(&lk); if (count == n) { mutex_unlock(&lk);//释放锁 goto retry; } count++;//获取锁后的操作 printf("("); mutex_unlock(&lk); } } void Tconsume() {//学生(消费者) while (1) { retry: mutex_lock(&lk); if (count == 0) { mutex_unlock(&lk); goto retry; } count--; printf(")"); mutex_unlock(&lk); } } int main(int argc, char *argv[]) { assert(argc == 2); n = atoi(argv[1]); setbuf(stdout, NULL); for (int i = 0; i < 8; i++) { create(Tproduce); create(Tconsume); } }