
【Linux】多线程---互斥锁,同步
发布日期:2021-05-10 06:33:34
浏览次数:5
分类:技术文章
本文共 3521 字,大约阅读时间需要 11 分钟。
1.互斥
- 想要保证互斥,我们需要用到互斥锁
- 互斥锁本身也是一个资源,或者我们也需要在代码中来获取互斥锁,一定只要多个线程保证互斥,需要都去获取互斥锁,否则就无法保证互斥
2.互斥锁
- 本质:在互斥锁内部当中有一个计数器,其实就是互斥量
- 当线程获取互斥锁的时候,如果计数器当中的值为0,表示当前线程获取不到互斥锁,也就是没有获取互斥锁,就不要在去获取临界资源了
- 当线程获取互斥锁的时候,如果计数器当中的值为1,表示当前线程可以获取到互斥锁,也就是意味着可以访问到临界资源,代码可以执行临界区当中的代码
- 问题:为什么计数器当中的值从0变成1,或者从1变成0,是原子操作(计数器当中的值如何保证原子性)
- 获取锁资源的时候(加锁) ① 寄存器当中的值直接赋值成为0 ② 将寄存器当中的值和计数器当中的值进行交换 ③ 判断寄存器当中的值,得出加锁的结果
当寄存器当中的值为1的时候,则表示可以加锁 当寄存器当中的值为0的时候,则表示不可以加锁
3.互斥锁的接口
- 初始化互斥锁变量
- 动态互斥锁
- pthread_mutex_t :互斥锁变量的类型
- int pthread_mutex_init(pthread_mutex_t * mutex, pthread_mutexattr_t *attr) mutex:传入互斥锁变量的地址 pthread_mutex_init会初始化互斥锁变量 attr:属性,一般传递NULL eg:pthread_mutex_t lock; pthread_mutex_init(&lock, NULL);
- 静态互斥锁 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
- 加锁
- int pthread_mutex_lock(pthread_mutex_t *mutex); // 阻塞加锁的接口
- mutex:传入互斥锁变量的地址 如果mutex当中的计数器的值为1,则pthread_mutex_lock接口就返回了,表示说加锁成功,同时计数器当中的值会被更改为0 如果mutex当中的计数器的值返回为0,则pthread_mutex_lock接口被阻塞了,pthread_mutex_lock接口没有返回,阻塞在该函数的内部,直接加锁成功
- int pthread_mutex_trylock(pthread_mutex_t *mutex)
- 非阻塞加锁接口
- 含义 当互斥锁变量的计数器置为1,则加锁成功返回 当互斥锁变量当中的计数器置为0,也会返回,但是一定要清楚,加锁并没有成功,也就是不要去访问临界资源 一般我们非阻塞接口都需要配合循环来使用 &nsbp;
- 带有超时时间的加锁接口
- int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout);
- 带有超时时间的接口,也就是意味着当不能直接获取互斥锁的时候,会等待abs_timeout时间 如果在这个时间内部加锁成功了,直接返回,不需要在继续等待剩余的时间,并且表示加锁成功 如果超过该事件,也返回掉了,但是表示加锁失败了,需要循环加锁
- 解锁
- int pthread_mutex_unlock(pthread_mutex_t * mutex)
- 不管是哪一个加锁接口成功的,都可以使用该接口进行解锁
- 解锁的时候,会讲互斥锁变量当中的计数器的值,从0变成1,表示其他线程可以获取互斥锁
- 销毁互斥锁
- pthread_mutex_destory(pthread_mutex_t *);
4.同步
- 同步为了保证各个线程对临界资源访问的合理性
- 条件变量:PCB等待队列+一堆接口(等待接口+唤醒接口)
5.条件变量的接口
- 初始化
- int pthread_cond_init(pthreaed_cond_t* cond, pthread_condattr_t* attr) cond:pthread_cond_t:条件变量的类型,传参的时候还是传入条件变量的地址 attr:条件变量的属性,通常传递NULL,采用默认属性
- 等待:将调用该接口的线程放到PCB等待队列当中
- int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex); cond:条件变量 mutex:互斥锁
- 思考: ① ②
- 唤醒
- int pthread_cond_signal(pthread_cond_t* cond) 作用:通过PCB等待队列当中的线程,将其从队列当中出来,唤醒该线程(唤醒至少一个PCB等待队列当中的线程)
- int pthread_cond_broadcast(pthread_cond_t * cond) 唤醒PCB等待队列当中全部的线程
- 释放
- int pthread_cond_destory(pthread_cond_t* cond)
#include#include #include #define THREADCOUNT 2int g_bowl = 0;pthread_mutex_t g_mut;pthread_cond_t g_cond;void* MakeStart(void *arg){ while(1) { pthread_mutex_lock(&g_mut); while(g_bowl > 0) { pthread_cond_wait(&g_cond, &g_mut); } g_bowl++; printf("i am make %p, g_bowl: %d\n", pthread_self(), g_bowl); pthread_mutex_unlock(&g_mut); pthread_cond_signal(&g_cond); } return NULL;}void* EatStart(void *arg){ while(1) { // eat pthread_mutex_lock(&g_mut); while(g_bowl <= 0) { pthread_cond_wait(&g_cond, &g_mut); } g_bowl--; printf("i am make %p, g_bowl: %d\n", pthread_self(), g_bowl); pthread_mutex_unlock(&g_mut); // 通知等待队列做面的人 pthread_cond_signal(&g_cond); } return NULL;}int main(){ pthread_mutex_init(&g_mut, NULL); pthread_cond_init(&g_cond, NULL); pthread_t prod[THREADCOUNT], cons[THREADCOUNT]; for(int i = 0; i < THREADCOUNT; i++) { int ret = pthread_create(&prod[i], NULL, MakeStart, NULL); if(ret < 0) { perror("prod create error!\n"); return -1; } ret = pthread_create(&prod[i], NULL, EatStart, NULL); if(ret < 0) { perror("cons create error!\n"); return -1; } } for(int i = 0; i < THREADCOUNT; i++) { pthread_join(prod[i], NULL); pthread_join(cons[i], NULL); } pthread_mutex_destroy(&g_mut); pthread_cond_destroy(&g_cond); return 0;}
转载地址:https://blog.csdn.net/weixin_43967449/article/details/110135504 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
感谢大佬
[***.8.128.20]2023年11月30日 19时00分16秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
学习笔记-数据结构与算法之栈与队列
2019-03-28
学习笔记-数据结构与算法之二叉树
2019-03-28
计算机网络知识学习(核心:网络协议)-- 应用层
2019-03-28
C++面试高频考点整理--基础
2019-03-28
【MATLAB】图像处理相关函数dftfilt函数
2019-03-28
【MATLAB】图像处理相关函数hpfilter函数
2019-03-28
冈萨雷斯Matlab版第五章(图像复原)知识点要点记录
2019-03-28
【MATLAB】图像处理相关函数imnoise2函数
2019-03-28
【MATLAB】图像处理相关函数imnoise3函数
2019-03-28
【MATLAB】图像处理相关函数adpmedian函数
2019-03-28
十大经典排序算法小结(附源码和菜鸟版注释)
2019-03-28
【数据结构】链表应用——箱子排序
2019-03-28
【C++】数组与矩阵
2019-03-28
十个问题——如何快速了解一个陌生行业/领域
2019-03-28
【TCP/IP网络协议】(三)IP网络协议
2019-03-28
【TCP/IP网络协议】(四)网络层其他协议
2019-03-28
【LeetCode】常更~
2019-03-28
img.item()函数说明
2019-03-28
Openfire安装报错及启动报错的解决方法探讨
2019-03-28
sqlserver特殊表
2019-03-28