Linux:互斥锁(附线程调试)

互斥的相关概念

  • 临界资源:多线程执行流共享的资源就叫做临界资源
  • 临界区:访问临界资源的代码,叫临界区
  • 互斥:任何时刻,互斥保证有且只有一个执行流进入临界区访问临界资源,通常对临界资源起保护作用
  • 原子性(后面讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成

互斥锁:保证多个执行流在访问临界资源时,是原子操作

加锁的本质是让所有的线程串行化

线程是可以在任何时间被切换,线程执行到临界区代码时被切换,是不会有其他线程进入临界区的
其他线程线程必须先申请锁
线程被切走,是带着锁走的

互斥锁原理

一条汇编语句就是一条原子性语句
寄存器中的数据,全部是线程内部上下文的数据,一个线程从CPU上被剥离走,必须带走自己的上下文数据
一个线程申请到了锁,被切换后,锁也就被拿走了

互斥锁底层是一个互斥量,互斥量的本质是计数器,值保存在内存中,计数器值只能为1(可以获取互斥锁),和0(不能获取互斥锁);

  • 互斥锁刚初始化出来的值是1,表示线程可以加锁,然后互斥锁计数器就从1变为0;
  • 其01的转化操作不是加减,而是将计数器的值和寄存器中的值,靠一条汇编指令将两者里的值进行交换;
  • 程序计数器的值可为0为1,而寄存器的值必须初始化为0;
  • 只需要判断交换完毕之后,寄存器中的值为1则加锁成功,为0则加锁失败

在这里插入图片描述

互斥锁接口

初始化接口:

  • 在这里插入图片描述

加锁接口:一般使用阻塞加锁

  • 在这里插入图片描述

解锁接口:

  • 不管用上述三个任何一个加锁,都能用该函数解锁
  • int pthread_mutex_unlock(pthread_mutex_t* mutex);
    参数是互斥锁变量的地址

线程和互斥锁的创建顺序

加锁位置:在临界资源前加锁
解锁位置:在所有可能导致线程退出的地方进行解锁

在这里插入图片描述

若没有20行和23行解锁代码

  • 假设线程A加锁完毕,未被加锁的三个线程等待加锁,
  • A运行完毕再次请求加锁,此时该锁已经被使用,线程A也会被阻塞,请求加锁
  • 使用pstack命令并不能看出哪个线程使用锁后再请求加锁在这里插入图片描述

查找方法:使用gdb调试
gdb attch +pid调式存在的进程,attch可以换成-p

  • 在这里插入图片描述

bt查看堆栈信息
thread apply all bt 查看所有线程堆栈信息
在这里插入图片描述在这里插入图片描述


现在要查找哪个线程使用了锁,就需要进入线程的堆栈;
在这里插入图片描述
由此可见是5696号线程使用了锁后,还想进行加锁操作

  • 所以需要进行解锁(上图代码中,break语句前后都是解锁操作);
  • 并且在所有可能导致线程退出的地方都应进行解锁(原因以及在代码部分标注)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值