作者简介:C/C++ 、Golang 领域耕耘者,创作者
个人主页:作者主页
专栏地址: 从原理解析go语言
刷题专栏:leetcode专栏
如果感觉博主的文章还不错的话,还请关注➕ 、点赞👍 、收藏🧡三连支持一下博主哦~~~
go 中的锁的底层理解是比较复杂的,但在go很多数据结构中都使用到了锁。如果深入了解并知道go 底层的锁是如何实现,不同的锁有啥区别,对于后面在项目中也很有帮助。
这一章节主要讲解一下四种锁
atomic的场景多协程累加经典例子
package main
import (
"fmt"
"sync/atomic"
"time"
)
func addP(p *int32) {
*p++
}
func main() {
c := int32(0)
// 并发实现对c的累加
for i := 0; i < 1000; i++ {
go addP(&c)
}
time.Sleep(time.Second * 1)
fmt.Println(c)
}
下面是随机运行的两个结果,可见此代码是充满随机性的,原因就是因为addP函数不是原子操作,在项目中我们显然不是要的这个结果


由于上面的例子不是我们想要的,现在我们来使用atomic 修改一下
package main
import (
"fmt"
"sync/atomic"
"time"
)
func addP(p *int32) {
//*p++ // 修改成下面一行
atomic.AddInt32(p, 1)
}
func main() {
c := int32(0)
// 并发实现对c的累加
for i := 0; i < 1000; i++ {
go addP(&c)
}
time.Sleep(time.Second * 1)
fmt.Println(c)
}
运行结果: 可以看到每次运行结果都是符合预定结果的

这里是两个线程操作未保护变量的例子,在上面的代码还中有1000个并发执行,所以说,像这样的代码充满了随机性

使用atomic 修改后的代码,查看汇编的过程,会发现里面加了一个锁

在上面我们使用了atomic 的累加功能,其实atomic还有一些功能,比如说下面的比较交换(CAS)、装载功能(load)等
CAS

他的功能就是将原先的值比较是不是old 值,如果是,换成100。 是将非原子操作换成原子操作
atomic.CompareAndSwapInt32(&c, 10, 100)
// 等于上面的一行代码
if c == 10 {
c = 100
}
load 功能
加载超过系统字长的值,可能需要多次,防止读取高位时,低位被改,就需要使用这个
使用atomic 中的这个功能,就能不受其他协程操作影响了
atomic.LoadInt64()
atomic 主要是将多个指令变成原子操作,防止其他协程操作的影响,在项目中,十分重要。


下面是获取锁的函数

获取锁: uint32 减1, 获取成功
释放锁: uint32 加1, 释放成功

获取锁: 协程休眠,进入堆树(就是上面提到的平衡二叉树)等待
释放锁: 从堆树中取出一个协程, 唤醒
sema 锁退化成一个专用休眠队列

下面是模拟三个人给小伙person 升职加薪
package main
import (
"fmt"
"sync"
"time"
)
type Person struct {
mtx sync.Mutex
salary int
level int
}
func (p *Person) promote() {
p.mtx.Lock()
p.salary += 1000
p.level += 1
fmt.Println(p.salary)
fmt.Println(p.level)
p.mtx.Unlock()
}
func main() {
p := Person{level: 1, salary: 10000}
// 模拟三个人给小伙p 升职加薪
go p.promote()
go p.promote()
go p.promote()
time.Sleep(time.Second)
}
/**不加锁
13000
4
11000
12000
4
4
加锁
11000
2
12000
3
13000
4
*/



sema == 0 就是休眠, 跟前面的章节对应上了



3. 这里也不是直接放出来后就能抢占到锁,会出现上面的情况

4. 然后这里就会跟上面的情况一样了

在上节说了,在大量竞争的情况下,有锁饥饿的情况
先看两幅图


上面两个截图,表示两种状态



推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习
如果此篇博客对你有帮助的话,可以动一动你的小手~~~
👍 点赞,你的认可是我创作的动力!
🧡 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!