锁的底层原理

我们写各类系统应用,常见的网络变成,基本上都是并发编程,不论是多线程还是多进程、或者是协程、队列等。这些并发场景在对共享变量进行访问时,会带来数据不一致问题,这时就需要用到锁或者原子操作保证数据一致性。
一、常见并发场景
1、单一数值的增减,如:秒杀活动库存的递减,投票数的增加。
2、对象结构的增减,如:优惠券的发送,在线用户列表。
二、并发编程的几个概念
1、并发执行不一定是并行执行
2、单核cpu可以并发执行,不能并行执行
并行是同一时刻多任务的处理,并发是同一时间段内的多任务处理。
区别:多核的并行处理涉及到同一时刻多核同时读一行缓存,存在脏读和脏写;单核的并发处理涉及到处理任务的中间变量存在脏写。
三、锁的作用
1、避免并行运算中,共享数据的的读写安全问题;
2、并行执行时,在锁的位置只有一个程序可以获得锁,其他程序无法获得;
3、锁的出现使得并行执行得地方在锁的位置执行串行;
四、锁的底层实现类型
1、锁的形式
(1)、锁内存总线:针对内存读写操作,在总线上进行控制,限制程序的内存访问;
(2)、锁缓存行:同一个缓存行的内容读写操作,cpu内部的高速缓存会保证一致性锁作用在同一个对象或者变量上。
现代cpu首先会在高速缓存上寻找,如果存在对象、变量就使用锁缓存行,否则使用锁内存总线;加锁对执行速度带来的不良影响,由上看加锁和解锁都是在高速缓存和总线上进行读写的,效率非常高,而出现的耗时问题主要在产生冲突时执行的串口化等待时间,以及上下文的切换。
2、CPU/缓存与锁
锁的底层实现原理与CPU/高速缓存有密切的联系,首先看一下CPU
在这里插入图片描述
内核独享L1、L2,共享L3;多颗CPU通过QPI进行连接,内存读写要通过内存总线,CPU与内存、磁盘、网络、外设等通信,都需要通过各种系统提供的系统总线。
编译器、CPU优化
编译器优化:重新代码排序,优先读操作(读更好的性能,因为cache中有共享数据,而写操作需要,会让数据失效)
CPU优化:指令执行乱序,(多核心协同处理,自动优化和重排指令顺序)
编译器、CPU屏蔽
优化屏蔽:禁止编译器做屏蔽,按照代码逻辑顺序生成二进制代码, volatile关键词;
内存屏蔽:禁止CPU优化,防止指令重排序,保证数据的可见性,store barrier, load barrier, full barrier;
写屏障:阻塞直到把store buff中的数据刷到cache中;
读屏障:阻塞直到把Invalid Queue中的消息执行完毕;
全屏障:包括读写屏障,保证各核数据一致性。

  那么golang中加锁加了什么?
  1、禁止编译器做优化(优化屏蔽);
  2、禁止CPU进行指令重排(内存屏蔽)
  3、针对缓存行和内存总线的控制;
  4、冲突时的任务等待队列。
  
 常见锁总结:
 自旋锁:只要没有锁上,就不断重试。
如果别的线程长期持有该锁,那么你这个线程就一直在 while while while 地检查是否能够加锁,浪费 CPU 做无用功。
优点:不切换上下文;
不足:烧CPU;
适用场景:冲突不多,等待时间不长的情况下,或者少次数的尝试自旋.

在这里插入图片描述

互斥锁:
操作系统负责线程调度,为了实现「锁的状态发生改变时再唤醒」就需要把锁也交给操作系统管理。
所以互斥器的加锁操作通常都需要涉及到上下文切换,操作花销也就会比自旋锁要大。
优点:简单高效;
不足:冲突等待时的上下文切换;
适用场景:绝大部分情况下都可以直接使用互斥锁
在这里插入图片描述
条件锁:
它解决的问题不是「互斥」,而是「等待」。
消息队列的消费者程序,在队列为空的时候休息,数据不为空的时候(条件改变)启动消费任务。
条件锁的业务针对性更强。
在这里插入图片描述
互斥锁操作:
在这里插入图片描述
在这里插入图片描述
大概的源码处理逻辑如下:
1 通过CAS操作来竞争锁的状态 &m.state;
2 没有竞争到锁,先主动自旋尝试获取锁 runtime_canSpin 和 runtime_doSpin (原地烧CPU);
3 自旋尝试失败,再次CAS尝试获取锁;
4 runtime_SemacquireMutex 锁请求失败,进入休眠状态,等待信号唤醒后重新开始循环;
5 m.state等待队列长度(复用的int32位数字,第一位是锁的状态,后31位是锁的等待队列长度计数器);

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值