Linux多线程——线程互斥与同步和其他概念

线程互斥

我们之前介绍过互斥的概念,但没有介绍Linux中线程互斥的操作

互斥存在的必要性是因为访问共享资源时,有可能被CPU换下,这样就会产生bug

例如说我们上一篇中说过的抢票,我们虽然设置的是当ticket小于等于0时结束线程

但是当五个线程几乎同时进入这个判断,就会导致过量运行

主要是因为这些操作并非原子的,不是原语

要解决这个问题就需要互斥锁

互斥锁的使用

互斥锁的使用一般分为四个步骤

  1. 初始化互斥锁
  2. 临界区前加锁
  3. 临界区后解锁
  4. 用完后销毁
初始化互斥锁

这里有两个方法,第一个是静态分配

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

第二个是动态分配

int pthread_mutex_init(pthread_mutex_t* restrict mutex, const pthread_mutexattr_t* restrict attr)

第一个是要初始化的互斥量,我们在调用之前声明一共传入即可,第二个我们传入NULL

加锁和解锁

int pthread_mutex_lock(pthread_mutex_t* mutex)

int pthread_mutex_unlock(pthread_mutex_t* mutex)

当原来的互斥量没有被加锁,此时加锁就会成功

当互斥量已经被上锁了,这个线程就会被阻塞,等待互斥量解锁

销毁互斥锁

静态的互斥锁不需要销毁

已经加锁的互斥量不允许被销毁

已经销毁的互斥量,要确保以后不会再被用到

int pthread_mutex_destory(pthread_mutex_t* mutex)

这里互斥锁的库要直接使用也是不方便的,我们同样可以给其封装成类会好用很多

线程死锁

死锁指的是一个线程或者几个线程互相阻塞等待,没有任何一个线程在运行

要避免陷入死锁可以尝试破坏以下几个条件

  • 互斥条件
  • 请求与保持:一个执行流被阻塞时依然占据其保持的其他资源
  • 不剥夺条件:一个执行流获得的资源在未使用完之前不能被强行剥夺
  • 循环等待条件

线程安全与可重入

线程安全指的是在多个线程并发执行同一段代码时,不会出现不同的结果

这里主要指的是对于全局变量和静态变量

重入指的是,同一个函数被不同的执行流调用时,当一个执行流还没有执行完成,另一个执行流就再次进入的情况。一个函数可重入就说明可以同时搭载多个执行流而不出现bug,否则就是不可重入函数

实际上可重入的条件比线程安全更加严格

下面的情况出现,就说这个函数不可重入,否则会出现bug

  • 调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
  • 标准IO库函数,标准IO库的很多实现都已不可重入的方式使用全局数据结构
  • 可重入函数体内使用了静态的数据结构

一般来说,函数可重入,那么线程一定是安全的,如果函数不可重入,那么就不允许多线程并发使用

线程同步

一方面是因为有可能资源被一个线程霸占,另一方面我们可能希望执行流有先后的执行顺序

同步就是让线程的执行流有先后的执行顺序

竞态条件指的是,因为时序问题,导致的程序问题

线程同步的接口

与互斥类似,线程同步也分为四部

  1. 初始化条件变量
  2. 利用条件变量等待资源就绪
  3. 资源就绪后唤醒线程来访问
  4. 使用后销毁条件变量
初始化条件变量
pthread_cond_t cond;//定义变量后再初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);

cond是要初始化的条件变量

attr传入NULL

利用条件变量等待资源就绪
int pthread_cond_wait(pthread_cond_t* restrict cond, pthread_mutex_t* restrict mutex)

要在cond这个条件变量上等待,mutex是互斥量

进程资源等待的前提是,拿到锁进入临界区,所以wait函数需要条件变量和互斥锁

唤醒等待
int pthread_cond_broadcast(pthread_cond_t* cond);
int pthread_cond_signal(pthread_cond_t* cond);

第一个是唤醒所有线程,是广播

第二个是唤醒某一个线程

销毁
int pthread_cond_destory(pthread_cond_t* cond);
  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栖林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值