文档章节

golang value并发安全的另一种玩法

anoty
 anoty
发布于 2017/04/17 20:19
字数 364
阅读 1175
收藏 11

golang value并发安全的另一种玩法,就是使用atomic.Value,看一段代码。

package main

import (
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	var m atomic.Value
	type Map map[string]string
	m.Store(make(Map))
	var mu sync.Mutex

	read := func(key string) (val string) {
		m1 := m.Load().(Map)
		return m1[key]
	}

	insert := func(key, val string) {
		mu.Lock()
		defer mu.Unlock()
		m1 := m.Load().(Map)
		m2 := make(Map)
		for k, v := range m1 {
			m2[k] = v
		}
		m2[key] = val
		m.Store(m2)
	}
	go func() {
		for {
			insert("k", "v")
			time.Sleep(100 * time.Millisecond)
		}
	}()
	go func() {
		for {
			read("k")
		}
	}()
	time.Sleep(10 * time.Second)
}

相对于读写锁,少了一些锁的争抢,不过相对的,带来了一些,内存上的开销,适用于读多写少并且变量占用内存不是特别大的情况,如果用内存存储大量数据,这个并不适合,技术上主要是常见的写时复制(copy-on-write)。

另外这个还比较适合程序配置的存储,贴一段官方的栗子

var config Value // holds current server configuration
// Create initial config value and store into config.
config.Store(loadConfig())
go func() {
        // Reload config every 10 seconds
        // and update config value with the new version.
        for {
                time.Sleep(10 * time.Second)
                config.Store(loadConfig())
        }
}()
// Create worker goroutines that handle incoming requests
// using the latest config value.
for i := 0; i < 10; i++ {
        go func() {
                for r := range requests() {
                        c := config.Load()
                        // Handle request r using config c.
                        _, _ = r, c
                }
        }()
}

恩,挺好玩的。

更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师

© 著作权归作者所有

anoty
粉丝 25
博文 42
码字总数 26186
作品 0
浦东
私信 提问
加载中

评论(4)

dingdayu
dingdayu

引用来自“littledriver”的评论

这个demo的好处,如作者所说,确实是少了一次读锁,减少了一些效率。但是我发现@dingdayu 这位同学问为什么需要一个m2的时候,作者貌似没有解释出真正的原因。之所以在m2上进行修改,把我们要insert的key和value插入进去,是因为,如果把insert当中的m2[key] = val改成m1[key]=val,那么在go1.6以及以后的版本里都会报错 fatal error: concurrent map read and map write。并发读写一个map本身就是不对的,这本应该由开发者来保证,但是go1.6之后的版本会为我们检测这种情况。所以,作者才使用了m2将m1中的内容都深拷贝出来,修改之后在通过store方法塞回去。避免了这种情况。https://blog.golang.org/go1.6 go1.6的发布文档中提到了这一点

https://my.oschina.net/u/222608/blog/881263

多谢,甚为感激,正是所需要的解答。
littledriver
littledriver
这个demo的好处,如作者所说,确实是少了一次读锁,减少了一些效率。但是我发现@dingdayu 这位同学问为什么需要一个m2的时候,作者貌似没有解释出真正的原因。之所以在m2上进行修改,把我们要insert的key和value插入进去,是因为,如果把insert当中的m2[key] = val改成m1[key]=val,那么在go1.6以及以后的版本里都会报错 fatal error: concurrent map read and map write。并发读写一个map本身就是不对的,这本应该由开发者来保证,但是go1.6之后的版本会为我们检测这种情况。所以,作者才使用了m2将m1中的内容都深拷贝出来,修改之后在通过store方法塞回去。避免了这种情况。https://blog.golang.org/go1.6 go1.6的发布文档中提到了这一点

https://my.oschina.net/u/222608/blog/881263
anoty
anoty

引用来自“dingdayu”的评论

请教,例子中的insert,添加一个键值,为啥要先创建m2,把m1循环放到m2,然后给m2加一个,然后再给m1啊?

m1和m2只是临时变量,最终是赋值给m。
dingdayu
dingdayu
请教,例子中的insert,添加一个键值,为啥要先创建m2,把m1循环放到m2,然后给m2加一个,然后再给m1啊?
Go圣经-学习笔记之封装还是组合

上一篇 Go圣经-学习笔记之方法 下一篇 Go圣经-学习笔记之方法值和表达式 通过结构体嵌入扩展类型 在前面文章中,已经介绍了结构体中的匿名成员。今天我们介绍下对象的行为集扩展。 上面的p对...

cdh0805010
2017/10/26
0
0
Go圣经-学习笔记之复合类型(二)

上一篇 Go圣经-学习笔记之复合类型 下一篇 Go圣经-学习笔记之复合数据结构(三) map介绍和简单使用 map是一种无序的key/value对的集合,在Go语言中,一个map就是一个hash表的引用。map中的key...

cdh0805010
2017/10/23
0
0
B站直播:使用Golang重构,流量最大的推送功能

1 悲剧直播推送功能 ****** 1.1 B站直播推送功能的困境 ***B站直播有个推送功能,就是这里,看到那个红色的数字没有,显示你关注的主播开播人数。 然后每个进入B站的用户,不管是不是直播的观...

anoty
2016/10/22
0
1
Golang 学习笔记(11)—— 反射

转载请注明出处:Golang 学习笔记(11)—— 反射 Golang 介绍 反射是程序执行时检查其所拥有的结构。尤其是类型的一种能力。这是元编程的一种形式。它同一时候也是造成混淆的重要来源。 每一...

ChainZhang
2018/01/05
0
0
golang VS php 性能对比

原文 http://www.isno.cn/2013/12/golang-vs-php/ 在工作的项目中,我的主要开发语言是php,因需求或者为弥补php的缺陷,需要为php做各种各样的扩展,比如php本身不支持线程,没有队列,进程也...

神仙
2013/12/19
28.2K
34

没有更多内容

加载失败,请刷新页面

加载更多

Datatables插件1.10.15版本服务器处理模式ajax获取分页数据实例解析

一、问题描述 前端需要使用表格来展示数据,找了一些插件,最后确定使用dataTables组件来做。 后端的分页接口已经写好了,不能修改。接口需要传入页码(pageNumber)和页面显示数据条数(pageSi...

OSC首席混子
7分钟前
0
0
基于虹软的Android的人脸识别SDK使用测试

现在有很多人脸识别的技术我们可以拿来使用;但是个人认为还是离线端的SDK比较实用;所以个人一直在搜集人脸识别的SDK;原来使用开源的OpenCV;最近有个好友推荐虹软的ArcFace, 闲来无事就下...

是哇兴哥棒棒哒
17分钟前
0
0
Netty内存池之PoolThreadCache详解

PoolThreadCahche是Netty内存管理中能够实现高效内存申请和释放的一个重要原因,Netty会为每一个线程都维护一个PoolThreadCache对象,当进行内存申请时,首先会尝试从PoolThreadCache中申请,...

爱宝贝丶
30分钟前
9
0
除了Reader、Inbox之外 谷歌“关门部”还关闭了哪些服务或产品?

我们经常调侃称谷歌的“关门部”和微软的“更名部”是 IT 界的两大传奇,那么除了比较熟悉的 RSS 订阅服务 Google Reader、电子邮件服务 Inbox 和 Facebook 竞品 Google+ 之外,你还知道谷歌...

linux-tao
30分钟前
0
0
从B站的代码泄露事件中,我们能学到些什么?

先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容。仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要...

程序猿DD
35分钟前
38
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部