Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24139 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

35 | 并发安全字典sync.Map (下)

郝林 2018-10-31
你好,我是郝林,今天我们继续来分享并发安全字典 sync.Map 的内容。
我们在上一篇文章中谈到了,由于并发安全字典提供的方法涉及的键和值的类型都是interface{},所以我们在调用这些方法的时候,往往还需要对键和值的实际类型进行检查。
这里大致有两个方案。我们上一篇文章中提到了第一种方案,在编码时就完全确定键和值的类型,然后利用 Go 语言的编译器帮我们做检查。
这样做很方便,不是吗?不过,虽然方便,但是却让这样的字典类型缺少了一些灵活性。
如果我们还需要一个键类型为uint32并发安全字典的话,那就不得不再如法炮制地写一遍代码了。因此,在需求多样化之后,工作量反而更大,甚至会产生很多雷同的代码。

知识扩展

问题 1:怎样保证并发安全字典中的键和值的类型正确性?(方案二)

那么,如果我们既想保持sync.Map类型原有的灵活性,又想约束键和值的类型,那么应该怎样做呢?这就涉及了第二个方案。
在第二种方案中,我们封装的结构体类型的所有方法,都可以与sync.Map类型的方法完全一致(包括方法名称和方法签名)。
不过,在这些方法中,我们就需要添加一些做类型检查的代码了。另外,这样并发安全字典的键类型和值类型,必须在初始化的时候就完全确定。并且,这种情况下,我们必须先要保证键的类型是可比较的。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(8)

  • sky
    郝大 go方面能推荐下比较成熟的微服务框架吗

    作者回复: 在我发布的Github优秀Go语言项目的思维导图里有。

    2018-11-01
    6
  • Timo
    做个sync.Map优化点的小总结:
    1. 空间换时间。 通过冗余的两个数据结构(read、dirty),实现加锁对性能的影响
    2. 使用只读数据(read),避免读写冲突。
    3. 动态调整,miss次数多了之后,将dirty数据提升为read
    4. 延迟删除。 删除一个键值只是打标记,只有在提升dirty的时候才清理删除的数据
    5. 优先从read读取、更新、删除,因为对read的读取不需要锁
    2019-05-30
    5
  • Rain
    这个脏字典让我想起了mysql的刷脏页。
    给老师点赞。
    2019-03-09
    1
  • 虢国技匠
    打卡
    2019-03-03
    1
  • 墨水里的鱼
    如何初始化reflect.Type?reflect.TypeOf(1) reflect.TypeOf("a") 只能这样吗?
    2018-11-30
    1
  • 渺小de尘埃
    当一个结构体里的字段是sync.map类型的,怎么json序列化呢?

    作者回复: 既然要序列化了就用不着同步了吧,用个普通map倒腾一下呗。或者你再包装一下,自定义序列化过程。

    2018-11-01
    1
  • Calios
    个人以为是读过的这个专栏里最精彩的一篇~ 只读字典和脏字典的实现好精彩,忍不住再去细细读一下sync.Map的实现。
    2019-08-14
  • 唐大少在路上。。。
    班门弄斧,其实有个细节帮老师丰富一下:
    两个原生map的定义为 map[interface{}]*entry
    其中的entry为一个只包含一个unsafe.pointer的结构体
    这里之所以value设置为指针类型,个人感觉就是为了在dirtry重建的时候直接把read里面这个entry的地址copy到dirty里面,这样当read中对entry里面的pointer执行原子替换的时候,dirty里面的值也会跟随着改变。
    这样,当每次对read已有key进行更新的时候就不用单独去操作一次dirty了
    2019-05-11
收起评论
8
返回
顶部