协作式原创查漏补缺之Golang中的锁

Posted yudidi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协作式原创查漏补缺之Golang中的锁相关的知识,希望对你有一定的参考价值。

预备知识

CAS机制

1. 是什么

参考附录3

CAS 是项乐观锁技术,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。
如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)
CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。”这其实和乐观锁的冲突检查 + 数据更新的原理是一样的。

扩展:
Q: 悲观锁和乐观锁的主要区别.
A:
乐观锁每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。
悲观锁在读取数据也会加锁,甚至只能有1个线程可以读取数据。

2. 图解CAS

讲解参考附录1的图解.

  1. 内存地址v(该地址的内容是内存实际值)
  2. old值: 旧的预期值
  3. new值: 要修改的新值
  • 关键问题:
    Q: 什么叫冲突
    A: 内存实际值和携程预期值不等就是冲突。 就是携程发现内存实际值(11)!=old值(10)就是冲突,本来该携程是要对10进行加1操作的.

3. Go中的CAS操作代码示例

讲解参考附录2的代码.

// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)

预备知识点: atomic.LoadInt64和atomic.StoreInt64,是一对原子操作,分别是读取和写入一个int。
TODO: 目前不清楚附录2中提到的错误写法有啥问题。

4. cas机制的缺点

  1. 高并发情况下自旋消耗cpu.(也就是compare老是失败)
  2. 只支持一个变量的原子操作,不支持多个变量(代码块)的原子操作. 代码块的原子操作,用sync.Mutex。
  3. CAS 会导致“ABA问题”。(参考附录4)

Q: mutex的底层实现

Q: go有哪些锁

扩展:所有锁的都可以归为4大类:

  1. 共享锁,独占锁
  2. 悲观锁,乐观锁 ?

A:

互斥锁 sync.Mutex
读写锁 sync.RWMutex

Q: 互斥锁是可重入锁吗

Q: 如何go实现可重入锁

参考资料

1.图解CAS
2.GO中CAS代码示例
3.CAS乐观锁,最精确的文字描述.
4.CAS会导致"ABA问题"
Go中锁的那些姿势,估计你不知道

以上是关于协作式原创查漏补缺之Golang中的锁的主要内容,如果未能解决你的问题,请参考以下文章

协作式原创查漏补缺之乐观锁与悲观锁TODO

半夜思考之查漏补缺 , Spring 中的 Bean 继承机制

半夜思考之查漏补缺, Spring 中的容器后处理器

1.Python重修之查漏补缺:基础

关于fork()函数的查漏补缺,赶紧来测测能答对几道题

关于fork()函数的查漏补缺,赶紧来测测能答对几道题