各类资料学习下载合集
链接:https://pan.quark.cn/s/7c8c391011eb
在多线程编程中,我们经常听到“同步”这个词。在现实生活中,比如阅兵方阵,同步意味着“大家一起做动作”(同时性);但在计算机科学中,同步(Synchronization)的意思恰恰相反——它强调的是协同步调,按预定的先后次序运行(顺序性)。
今天我们就来探讨为什么多线程需要同步,以及如果没有同步,世界会乱成什么样。
一、 为什么会发生“数据混乱”?
在多线程环境下,数据混乱(Data Chaos)通常由三个要素共同导致,这也是我们解决问题的根本逻辑:
- 资源共享:多个线程访问同一块内存(必要条件)。
- 调度随机:操作系统分配 CPU 时间片是随机的,线程随时可能被暂停(不可控)。
- 缺乏同步:没有机制来控制访问的顺序(这是唯一我们可以解决的)。
当这三者同时存在时,就会引发与时间有关的错误(Time-related errors)。我们通过两个经典案例来复现这种灾难。
二、 经典案例一:银行取钱问题
1. 场景描述
假设有一个银行账户余额50000 元。
- 丈夫(线程 A):拿着存折去柜台取20000 元。柜台操作慢,查询余额后需要确认签字(模拟耗时)。
- 妻子(线程 B):拿着银行卡去 ATM 取20000 元。ATM 操作快。
预期结果:50000 - 20000 - 20000 =10000 元。
2. 代码复现 (bank_race.c)
为了模拟“调度随机”和操作耗时,我们在读取余额和写入余额之间强制加入usleep,人为制造 CPU 切出的机会。
#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<unistd.h>// 共享资源:银行账户余额intbalance=50000;void*withdraw(void*arg){intamount=(int)(long)arg;intcur_balance;// 1. 读取当前余额 (Load)cur_balance=balance;printf("--- [线程 %lu] 查询余额: %d, 准备取款: %d\n",pthread_self(