重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
摘要: 一、前言 go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中CAS操作 二、CAS操作 go中的Cas操作与java中类似,都是借用了CPU提供的原子性指令来实现。
十余年的梨林网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。全网整合营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整梨林建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联公司从事“梨林网站设计”,“梨林网站推广”以来,每个客户项目都认真落实执行。
go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中CAS操作
go中的Cas操作与java中类似,都是借用了CPU提供的原子性指令来实现。CAS操作修改共享变量时候不需要对共享变量加锁,而是通过类似乐观锁的方式进行检查,本质还是不断的占用CPU 资源换取加锁带来的开销(比如上下文切换开销)。下面一个例子使用CAS来实现计数器
go中CAS操作具有原子性,在解决多线程操作共享变量安全上可以有效的减少使用锁所带来的开销,但是这是使用cpu资源做交换的。
我简单列举了并发编程的大纲,需要详细的私信“555”~~
go语言的map多协程访问时需要加锁
支持==和!=操作就可以做key,实际上只有function、map、slice三个kind不支持作为key,因为只能和nil比较不能和另一个值比较。布尔、整型、浮点、复数、字符串、指针、channel等都可以做key。
struct能不能做key要看每一个字段,如果所有字段都可以做key,那这个struct就可以。有一个字段不能做key,这个struct就不能做key。array也是,元素类型能做key,那这个array就可以。
例如:
type Foo map[struct {
B bool
I int
F float64
C complex128
S string
P *Foo
Ch chan Foo
}]bool
每一个字段都可以做key,Foo就可以做key。再如:
type Foo map[struct {
Fn func() Foo
M map[*Foo]int
S []Foo
}]bool
有一个字段不能做key、Foo就不允许做key,而这三个字段都不能。
字段是递归检查的:
type Foo map[struct {
Sub struct {
M map[*Foo]bool
}
}]bool
Sub的M字段不能做key,Sub就不能做key,Foo也就不能做key。
总之想把一个数据结构用于map的key,就不能包含function、map和slice。
sync.Map是1.9才推荐的并发安全的map,除了互斥量以外,还运用了原子操作,所以在这之前,有必要了解下 Go语言——原子操作
go1.10\src\sync\map.go
entry分为三种情况:
从read中读取key,如果key存在就tryStore。
注意这里开始需要加锁,因为需要操作dirty。
条目在read中,首先取消标记,然后将条目保存到dirty里。(因为标记的数据不在dirty里)
最后原子保存value到条目里面,这里注意read和dirty都有条目。
总结一下Store:
这里可以看到dirty保存了数据的修改,除非可以直接原子更新read,继续保持read clean。
有了之前的经验,可以猜测下load流程:
与猜测的 区别 :
由于数据保存两份,所以删除考虑:
先看第二种情况。加锁直接删除dirty数据。思考下貌似没什么问题,本身就是脏数据。
第一种和第三种情况唯一的区别就是条目是否被标记。标记代表删除,所以直接返回。否则CAS操作置为nil。这里总感觉少点什么,因为条目其实还是存在的,虽然指针nil。
看了一圈貌似没找到标记的逻辑,因为删除只是将他变成nil。
之前以为这个逻辑就是简单的将为标记的条目拷贝给dirty,现在看来大有文章。
p == nil,说明条目已经被delete了,CAS将他置为标记删除。然后这个条目就不会保存在dirty里面。
这里其实就跟miss逻辑串起来了,因为miss达到阈值之后,dirty会全量变成read,也就是说标记删除在这一步最终删除。这个还是很巧妙的。
真正的删除逻辑:
很绕。。。。