操作系统中锁的底层原理

在多线程中,为了保证数据操作的一致性,操作系统引入了锁机制,用于保证临界区代码的安全。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作系统的一致性,

所谓的锁说白了就是内存中的一个整型数,拥有两种状态:空闲状态上锁状态

看锁无非就是这几句

1、read lock;

2、判断lock状态;

3、如果已经加锁,失败返回;

4、把锁状态设置为上锁;

5、返回成功。

那什么时候会导致两个线程同时以获得锁呢

1、中断:假设线程A执行完第一步,发生中断,中断返回后,OS调度线程B,线程B也来加锁并且加锁成功,这时OS调度线程A执行,线程从第二步开始执行,也加锁成功。

2、多核:当然了,想想上面举的例子,描述的就是两个核同时获取到锁的情况。

解决方法1只有中断可以把上锁过程打断,造成多线程操作失败,我先关中断就好了,在加锁操作完成后再开中断,但是这样太笨了,

test and set 指令就是用来做一种加锁的原子操作,只要让不被中断就好了

在多核状态下,我们在锁内存总线的状态下执行test and set操作,就能保证同时只有一个核来test and set,从而避免了多核下发生的问题。

go面试题:锁的实现原理sync-mutex篇

Go面试题(四):锁的实现原理sync-mutex篇 - 掘金 (juejin.cn)

在Go中对于并发程序进行公共资源的访问的限制最常用的就是互斥锁(sync.mutex)的方式

sync.mutex的常用方法有两个:

  • Mutex.lock()用来获取锁
  • Mutex.Unlock()用于释放锁

在 Lock 和 Unlock 方法之间的代码段称为资源的临界区,这一区间的代码是严格被锁保护的,是线程安全的,任何一个时间点最多只能有一个goroutine在执行

互斥锁中有两个变量 state和sema

互斥锁state主要记录了四种状态

1当前等待这个锁的数量

2当前锁是否处于饥饿状态

3当前锁是否有goroutine已被唤醒

4当前锁是否被goroutine唤醒

sema信号量的作用:当持有锁的gorouine释放锁,会释放sema信号量,这个信号量会唤醒之前抢锁阻塞的gorouine来获取锁

锁的两种模式,正常模式饥饿模式

注意事项:

‘1在一个goroutine中执行Lock()加锁成功后,不要重复加锁,否则会panic

2在Lock()之前执行Unlock()释放锁 会panic

3对于同一把锁,可以在一个goroutine中执行Lock加锁成功后,可以在另外一个gorouine中执行Unlock释放这把锁

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值