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锁记的更多相关文章

  1. golang锁

    golang锁包:https://studygolang.com/pkgdoc sync.Mutex是一个互斥锁 var lock sync.Mutex 加锁段在中 lock.lock() lock. ...

  2. 详解golang net之netpoll

    golang版本1.12.9:操作系统:readhat 7.4 golang的底层使用epoll来实现IO复用.netPoll通过pollDesc结构体将文件描述符与底层进行了绑定.netpoll实现 ...

  3. MySQL实战45讲学习笔记:第二十讲

    一.引子 在上一篇文章最后,我给你留了一个关于加锁规则的问题.今天,我们就从这个问题说起吧. 为了便于说明问题,这一篇文章,我们就先使用一个小一点儿的表.建表和初始化语句如下(为了便于本期的例子说明, ...

  4. golang 互斥锁和读写锁

    golang 互斥锁和读写锁 golang中sync包实现了两种锁Mutex(互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. ty ...

  5. 记一次golang的实践

    之前做过一个深交所股票数据的接存储软件,消息的协议是这样. 协议文档在这  https://wenku.baidu.com/view/d102cd0b4a73f242336c1eb91a37f111f ...

  6. 记一次坑爹的golang 二维map判断问题

    记一次坑爹的golang 二维map判断问题 2018年10月18日 23:16:21 yinnnnnnn 阅读数:32更多 个人分类: golang   版权声明:本文为博主原创文章,未经博主允许不 ...

  7. 使用Golang利用ectd实现一个分布式锁

    http://blog.codeg.cn/post/blog/2016-02-24-distrubute-lock-over-etcd/ By zieckey · 2016年02月24日 · 1205 ...

  8. Golang 读写锁RWMutex 互斥锁Mutex 源码详解

    前言 Golang中有两种类型的锁,Mutex (互斥锁)和RWMutex(读写锁)对于这两种锁的使用这里就不多说了,本文主要侧重于从源码的角度分析这两种锁的具体实现. 引子问题 我一般喜欢带着问题去 ...

  9. golang 并发锁的陷阱

    错误代码示例 package main import ( "sync" "strconv" "fmt" ) type Node struct ...

随机推荐

  1. BZOJ 1196 公路修建问题(二分+最小生成树)

    题目要求求出图中的一颗生成树,使得最大的边权最小,且满足一级公路的个数>=k. 考虑二分最大边,问题就变为给出的图的生成树中,是否满足所有的边<=val,且一级公路的个数>=k. 所 ...

  2. 【bzoj4832】[Lydsy2017年4月月赛]抵制克苏恩 概率期望dp

    题目描述 你分别有a.b.c个血量为1.2.3的奴隶主,假设英雄血量无限,问:如果对面下出一个K点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输入 输入包含多局游戏. 第一行包含一个整数 T (T ...

  3. BZOJ4710 JSOI2011分特产(容斥原理+组合数学)

    显然可以容斥去掉每人都不为空的限制.每种物品分配方式独立,各自算一个可重组合乘起来即可. #include<iostream> #include<cstdio> #includ ...

  4. 【题解】Atcoder AGC#03 E-Sequential operations on Sequence

    仙题膜拜系列...首先我们可以发现:如果在截取了一段大的区间之后再截取一段小的区间,显然是没有什么用的.所以我们可以将操作序列变成单调递增的序列. 然后怎么考虑呢?启示:不一定要考虑每一个数字出现的次 ...

  5. 【题解】Atcoder ARC#97 F-Monochrome Cat

    好zz啊我……(:д:) 首先我们可以删掉所有只有黑色节点的子树(一定不会遍历到), 且注意到每一个点你一定只会经过一遍.然后又考虑如果起点和终点相同,那么总次数实际上已经固定了:就是遍历整棵树(每一 ...

  6. P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)

    题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...

  7. Android 手势识别

    public class MyGesture extends SimpleOnGestureListener { private GestureDetector gd; // onGestureLis ...

  8. [Leetcode] gas station 气站

    There are N gas stations along a circular route, where the amount of gas at station i isgas[i]. You ...

  9. UVA.674 Coin Change (DP 完全背包)

    UVA.674 Coin Change (DP) 题意分析 有5种硬币, 面值分别为1.5.10.25.50,现在给出金额,问可以用多少种方式组成该面值. 每种硬币的数量是无限的.典型完全背包. 状态 ...

  10. codeforces的dp专题

    1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个 ...