golang锁记
golang中有两个锁实现
atomic的CAS实现锁
首先是inter cpu,熟悉汇编的人都知道,inter指令集有个lock,如果某个指令集前面加个lock,那么在多核状态下,某个核执行到这个前面加lock的指令的时候,inter会让总线锁住,当这个核把这个指令执行完了,再开启总线!这是一种最最底层的锁!!
HLT 指令(停止处理器)停止处理器直至接收到一个启用中断(比如 NMI 或 SMI,正 常情况下这些都是开启的)、调试异常、BINIT#信号、INIT#信号或 RESET#信号。处理 器产生一个特殊的总线周期以表明进入停止模式。 硬件对这个信号的响应有好几个方面。前面板上的指示灯会打亮,产生一个记录 诊断信息的 NMI 中断,调用复位初始化过程(注意 BINIT#引脚是在 Pentium Pro 处理器 引入的)。如果停机过程中有非唤醒事件(比如 A20M#中断)未处理,它们将在唤醒停 机事件处理之后的进行处理。
在修改内存操作时,使用 LOCK 前缀去调用加锁的读-修改-写操作(原子的)。这种 机制用于多处理器系统中处理器之间进行可靠的通讯,具体描述如下: 在 Pentium 和早期的 IA-32 处理器中,LOCK 前缀会使处理器执行当前指令时产生 一个 LOCK#信号,这总是引起显式总线锁定出现。 在 Pentium 4、Intel Xeon 和 P6 系列处理器中,加锁操作是由高速缓存锁或总线 锁来处理。如果内存访问有高速缓存且只影响一个单独的高速缓存线,那么操作中就 会调用高速缓存锁,而系统总线和系统内存中的实际内存区域不会被锁定。同时,这 条总线上的其它 Pentium 4、Intel Xeon 或者 P6 系列处理器就回写所有的已修改数据 并使它们的高速缓存失效,以保证系统内存的一致性。如果内存访问没有高速缓存且/ 或它跨越了高速缓存线的边界,那么这个处理器就会产生 LOCK#信号,并在锁定操作期 间不会响应总线控制请求。
IA-32 处理器提供有一个 LOCK#信号,会在某些关键内存操作期间被自动激活,去锁定系统总线。当这个输出信号发出的时候,来自其它处理器或总线代理的总线控制请求将被阻塞。软件能够通过预先在指令前添加 LOCK 前缀来指定需要 LOCK 语义的其它场合。在 Intel386、Intel486、Pentium 处理器中,明确地对指令加锁会导致 LOCK#信号的产生。由硬件设计人员来保证系统硬件中 LOCK#信号的可用性,以控制处理器间的内IA-32 架构软件开发人员指南 卷 3:系统编程指南170存访问。对于 Pentium 4、Intel Xeon 以及 P6 系列处理器,如果被访问的内存区域是在处理器内部进行高速缓存的,那么通常不发出 LOCK#信号;相反,加锁只应用于处理器的高速缓存(参见 7.1.4.LOCK 操作对处理器内部高速缓存的影响) 。
当然inter还有其他方式保证原子操作!
然后是ARM cpu, arm主要是靠两个指令来保证原子操作的,LDREX 和 STREX
LDREX
LDREX 可从内存加载数据。
如果物理地址有共享 TLB 属性,则 LDREX 会将该物理地址标记为由当前处理器独占访问,并且会清除该处理器对其他任何物理地址的任何独占访问标记。
否则,会标记:执行处理器已经标记了一个物理地址,但访问尚未完毕。
STREX
STREX 可在一定条件下向内存存储数据。 条件具体如下:
如果物理地址没有共享 TLB 属性,且执行处理器有一个已标记但尚未访问完毕的物理地址,那么将会进行存储,清除该标记,并在Rd 中返回值 0。
如果物理地址没有共享 TLB 属性,且执行处理器也没有已标记但尚未访问完毕的物理地址,那么将不会进行存储,而会在Rd 中返回值 1。
如果物理地址有共享 TLB 属性,且已被标记为由执行处理器独占访问,那么将进行存储,清除该标记,并在Rd 中返回值 0。
如果物理地址有共享 TLB 属性,但没有标记为由执行处理器独占访问,那么不会进行存储,且会在Rd 中返回值 1。
mutex 是互诉锁
mutex lock 后,另外的线程lock时context就休眠了,当主线程执行完后唤醒等待的线程的实现方式。
mutex和atomic性能哪个好?
当然是atomic,因为mutex的实现lock时就调用了atomic。而mutex才是真正线程安全的,而atomic不一定,因为atomic要依靠cpu的lock指令的支持,不过我觉得golang应该做这些兼容实现。atomic是实现整个低核的lock,不适合在长时间锁定场景,因为很有可能引起整个系统卡住,所以一般是短锁场景,比如addint32,一个简单的计算或交换操作。而在长计算锁定的场景,还是使用mutex靠谱!
type Mutex struct {
key int32
sema uint32
}
func (m *Mutex) Lock() {
if atomic.AddInt32(&m.key, 1) == 1 {
// changed from 0 to 1; we hold lock
return
}
runtime_Semacquire(&m.sema)
}
func (m *Mutex) Unlock() {
switch v := atomic.AddInt32(&m.key, -1); {
case v == 0:
// changed from 1 to 0; no contention
return
case v == -1:
// changed from 0 to -1: wasn't locked
// (or there are 4 billion goroutines waiting)
panic("sync: unlock of unlocked mutex")
}
runtime_Semrelease(&m.sema)
}
golang锁记的更多相关文章
- golang锁
golang锁包:https://studygolang.com/pkgdoc sync.Mutex是一个互斥锁 var lock sync.Mutex 加锁段在中 lock.lock() lock. ...
- 详解golang net之netpoll
golang版本1.12.9:操作系统:readhat 7.4 golang的底层使用epoll来实现IO复用.netPoll通过pollDesc结构体将文件描述符与底层进行了绑定.netpoll实现 ...
- MySQL实战45讲学习笔记:第二十讲
一.引子 在上一篇文章最后,我给你留了一个关于加锁规则的问题.今天,我们就从这个问题说起吧. 为了便于说明问题,这一篇文章,我们就先使用一个小一点儿的表.建表和初始化语句如下(为了便于本期的例子说明, ...
- golang 互斥锁和读写锁
golang 互斥锁和读写锁 golang中sync包实现了两种锁Mutex(互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. ty ...
- 记一次golang的实践
之前做过一个深交所股票数据的接存储软件,消息的协议是这样. 协议文档在这 https://wenku.baidu.com/view/d102cd0b4a73f242336c1eb91a37f111f ...
- 记一次坑爹的golang 二维map判断问题
记一次坑爹的golang 二维map判断问题 2018年10月18日 23:16:21 yinnnnnnn 阅读数:32更多 个人分类: golang 版权声明:本文为博主原创文章,未经博主允许不 ...
- 使用Golang利用ectd实现一个分布式锁
http://blog.codeg.cn/post/blog/2016-02-24-distrubute-lock-over-etcd/ By zieckey · 2016年02月24日 · 1205 ...
- Golang 读写锁RWMutex 互斥锁Mutex 源码详解
前言 Golang中有两种类型的锁,Mutex (互斥锁)和RWMutex(读写锁)对于这两种锁的使用这里就不多说了,本文主要侧重于从源码的角度分析这两种锁的具体实现. 引子问题 我一般喜欢带着问题去 ...
- golang 并发锁的陷阱
错误代码示例 package main import ( "sync" "strconv" "fmt" ) type Node struct ...
随机推荐
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- hadoop 编码实现文件传输、查看等基本文件控制
hadoop集群搭建参考:https://www.cnblogs.com/asker009/p/9126354.html 1.创建一个maven工程,添加依赖 <?xml version=&qu ...
- 【刷题】HDU 4405 Aeroplane chess
Problem Description Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled fr ...
- pandas模块(数据分析)------dataframe
DataFrame DataFrame是一个表格型的数据结构,含有一组有序的列,是一个二维结构. DataFrame可以被看做是由Series组成的字典,并且共用一个索引. 一.生成方式 import ...
- linux下,手动切换jdk
1.首先将自定义的jdk目录安装到alternatives中 seven@ThinkPad:~/srcAndroid/src4..4_r1$ sudo update-alternatives --in ...
- ipython 安装和更新
pip install ipython pip install --upgrade ipython pip install --upgrade pip 不管是用pip装什么模块,前面都尽量不要加sud ...
- HDU1281: 棋盘游戏(二分图匹配)
棋盘游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Lodash js数据操作库
https://lodash.com/docs/4.17.4
- 洛谷 P1044 栈
题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要性不言自明,任何 ...
- Informatica _组件使用介绍及优化
转载 http://blog.csdn.net/yongjian1092/article/details/52588434 有空自己会写一个关于这方面的文章.