锁的作用,类型以及死锁

为什么需要锁

    我们知道线程是可以共享进程的资源的,当多个进程同时使用同一个资源的时候,就会发生问题,下图展示了两个线程对同一个变量进行加法运算时的情况,理想状态下。A线程对i=50进行加+1后i=51,之后cpu切换线程B继续进行加1运算,此时i=52。但程序在实际运行中可能会出现错误,如下图:

蓝色表示线程 1 ,红色表示线程 2

    当多线程相互竞争操作共享变量时,由于运气不好,即在执行过程中发生了上下文切换,我们得到了错误的结果,称之为竞争。操作共享资源的发代码成为临界区,为了解决竞争问题,我们可以让临界区互斥,也就是一个线程在临界区时,另一个线程应该阻塞。

互斥

互斥的实现

    为了实现线程的互斥,我们引入了两种方法

  1. :加锁、解锁操作;
  2. 信号量:P、V 操作;

互斥锁与自旋锁

    若线程先进入临界区,需要先进行加锁操作,如果加锁顺利则可以进入临界区,如果临界区执行完后,再进行解锁,释放临界区的资源

加锁-解锁

自旋锁:当前的线程无法获取锁时候回一直循环,不做任何事情,称为忙等待锁。如果是单CPU的话,不会运行其他线程,所以自旋锁永远也不会得到临界资源,从而一直等待,CPU也不会切换执行其他线程,所以自旋锁会一直占用CPU

无等待锁:也称互斥锁,无等待锁是相对于自旋锁说的,当线程拿不到资源的时候,不会占用CPU资源等待,而是将线程放入到锁的等待队列,然后将CPU让给其他线程。当线程 A 加锁成功后,此时互斥锁已经被线程 A 独占了,只要线程 A 没有释放手中的锁,线程 B 加锁就会失败,于是就会释放 CPU 让给其他线程,既然线程 B 释放掉了 CPU,自然线程 B 加锁的代码就会被阻塞对于互斥锁加锁失败而阻塞的现象,是由操作系统内核实现的

    正是由于内核帮我们切换进程,所以互斥锁存在着性能开销,来自于线程的两次切换:

  • 线程加锁失败时,内核会把线程的状态从「运行」状态设置为「睡眠」状态,然后把 CPU 切换给其他线程运行;
  • 接着,当锁被释放时,之前「睡眠」状态的线程会变为「就绪」状态,然后内核会在合适的时间,把 CPU 切换给该线程运行。

    所以,如果你能确定被锁住

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值