pthread_mutex_t & pthread_cond_t 总结一、多线程并发1.1 多线程并发引起的问题我们先来看如下代码:
#include <stdio.h>#include <pthread.h>#include <unistd.h>#define MAX 1E7int giNum = 0;void *func1(void *arg){ int i; for (i = 1; i <= MAX; i++) { giNum++; } return NULL;}void *func2(void *arg){ int i; for (i = 1; i <= MAX; i++) { giNum++; } return NULL;}int main(){ pthread_t th1; pthread_create(&th1, NULL, func1, NULL); pthread_t th2; pthread_create(&th2, NULL, func2, NULL); pthread_join(th1, NULL); pthread_join(th2, NULL); printf("giNum = %d\n", giNum); return 0;}代码的内容很简单:
- 创建了两个子线程 th1、th2
- 两个子线程分别执行giNum++操作
- 最后输出giNum的值
- th1 运行时giNum++要执行 \(10^7\) 次
- th2 运行时giNum++也要执行 \(10^7\) 次
文章插图
多次运行,你会发现,仅有一次(甚至没有)结果是正确的 。
1.2 知根知底上述代码得到的结果为什么不如顺序执行所预期的那样呢?可以用程序修改变量值时所经历的三个步骤解释这个现象:
- 从内存单元读入寄存器
- 在寄存器中对变量操作(加/减1)
- 把新值写回到内存单元
- 内存中读取 giNum;
- 将 giNum++;
- 将 giNum 写入到内存 。
二、线程锁2.1 互斥量多线程程序中可能会存在数据不一致的情况,那么如何保证数据一致呢?可以考虑同一时间只有一个线程访问数据 。
而互斥量(mutex)就是一把锁 。多个线程只有一把锁一个钥匙,谁上的锁就只有谁能开锁 。当一个线程要访问一个共享变量时,先用锁把变量锁住,然后再操作,操作完了之后再释放掉锁;当另一个线程也要访问这个变量时,发现这个变量被锁住了,无法访问,它就会一直等待,直到锁没了,它再给这个变量上个锁,然后使用,使用完了释放锁,以此进行 。这样即使有多个线程同时访问这个变量,也好像是对这个变量的操作是顺序进行的 。
互斥变量使用特定的数据类型:pthread_mutex_t 。使用互斥量前要先初始化,初始化又分为静态初始化和动态初始化:
- 静态初始化:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
- 动态初始化:pthread_mutex_init(&mutex,NULL);
经验总结扩展阅读
- VLQ & Base64 VLQ 编码方式的原理及代码实现
- MYSQL-->InnoDB引擎底层原理
- StampedLock:一个并发编程中非常重要的票据锁
- Longchamp龙骧饺子包
- <三>从编译器角度理解C++代码编译和链接原理
- <一>关于进程虚拟地址空间区域内存划分和布局
- GitLab私有化部署 - CI/CD - 持续集成/交付/部署 - 源代码托管 & 自动化部署
- 🔥支持 Java 19 的轻量级应用开发框架,Solon v1.10.4 发布
- Bert不完全手册9. 长文本建模 BigBird & Longformer & Reformer & Performer
- XXI Open Cup, Grand Prix of Belarus 2020-2021 Winter Petrozavodsk Camp, Belarusian SU Contest 题解