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);
第一种方法仅局限于静态初始化的时候使用:将「声明、定义、初始化」一气呵成,除此之外的情况都只能使用 pthread_mutex_init函数 。2.2 pthread_mutex_init函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
头 文 件:#include <pthread.h>
返 回 值:成功返回 0,失败返回错误码
参数介绍:
- mutex:指向 pthread_mutex_t 声明的变量的地址
- attr:指定了新建互斥锁的属性 。一般置为 NULL(如果参数attr为 NULL,则使用默认的互斥锁属性,默认属性为快速互斥锁 ) 。
restrict 关键字只用于限制指针 。告诉编译器所有修改该指针指向内存中的操作,只能通过本指针完成,不能通过除了本指针之外的变量或指针修改 。推荐阅读
- 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 题解