本文主要分享的是线程间通信的基本概念以及锁的相关函数接口,锁是解决线程间通信时资源竞争的一个重要的方法,但是它的特点是依然避免不了CPU在线程间无序的任务调度机制,因此使得几个线程是异步的,要想使得几个线程有序的同步的去处理业务,就需要用到我们后面的信号量:
线程间通信: 不同线程间数据的传输
1.资源:
代码、变量、CPU、内存相关设备都可以看成是任务运行中需要的资源
2.互斥锁:
互斥锁为防止多线程间资源竞争的问题,操作共享资源时先加锁,操作资源后解锁,能够防止多线程同时访问资源
3.临界资源:
同一时刻只允许一个线程任务操作的资源称为临界资源
4.临界区:
加锁和解锁中间的代码,同一时刻不能同时执行的代码区域
5.函数接口:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
功能: 互斥锁的初始化
参数:
mutex:锁变量空间首地址
attr:互斥锁属性空间首地址(NULL)
返回值:
成功返回0
失败返回-1
int pthread_mutex_lock(pthread_mutex_t *mutex)
功能:
互斥锁上锁
参数:
mutex:互斥锁空间首地址
返回值:
成功返回0
失败返回-1
注意:加锁的时候一般给被竞争的资源都需要加锁,都需要去限制
int pthread_mutex_unlock(pthread_mutex_t *mutex)
功能: 互斥锁解锁
参数: mutex:互斥锁空间首地址
返回值:
成功返回0
失败返回-1
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能: 销毁互斥锁
参数: mutex:互斥锁空间首地址
返回值:
成功返回0
失败返回-1
6.原子操作
CPU不会被任务调度所打断的一次操作,成为原子操作
7.锁的应用场景
多线程操作全局数据,需对全局数据加锁
8.死锁
由于加锁错误导致多个任务均被阻塞,无法继续执行下去的状态,称为死锁
产生的必要条件:
(1)不可剥夺条件 :如果一个任务已经加锁,另外一个任务不能强制夺取锁资源
(2)互斥条件 :锁同一时刻只能被一个任务使用
(3)请求保持条件 :一直请求申请锁资源
(4)循环等待条件 :如果没有申请到锁资源,一直等待锁资源
解决方法:
(1)使用pthread_mutex_trylock替代pthread_mutex_lock
(2)加锁顺序保持一致
本期的分享到这里就结束啦,希望各位小伙伴们加油学习,一起进步哦!欢迎评论区提问留言哦!