用CAS操作实现Go标准库中的Once
Go标准库中提供了Sync.Once来实现“只执行一次”的功能。学习了一下源代码,里面用的是经典的双重检查的模式:
// Once is an object that will perform exactly one action.
type Once struct {
m Mutex
done uint32
}
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
f()
atomic.StoreUint32(&o.done, 1)
}
}
我觉得这里也可以用Go的原子操作来实现“只执行一次”,代码更简单,而且比起用Mutex的开销要更小一些:
type Once struct {
done int32
}
func (o *Once) Do(f func()) {
if atomic.LoadInt32(&o.done) == 1 {
return
}
// Slow-path.
if atomic.CompareAndSwapInt32(&o.done, 0, 1) {
f()
}
}
熟悉Java内存模型的程序员可能会留意到上面的CAS操作中传递的是变量地址。如果在Java中,这样的变量是需要volatile来保证线程之间的可见性的,而Golang并没有volatile,Golang的内存模型的happen-after规则也没有提到atomic操作。但从Golang标准库的相关源码来看,Golang的atomic操作应该是可以满足可见性要求的。
从下面的测试上看,这样实现没有什么并发的bug。
runtime.GOMAXPROCS(1000)
n := 100000
wg := new(sync.WaitGroup)
wg.Add(n)
a := int32(0)
for i := 0; i < n; i++{
go func(){
if atomic.CompareAndSwapInt32(&a, 0, 1) {
fmt.Println("Change a to 1")
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("Test is done")
Go的内存模型文档中对atomic包并未提起,如果参考Java的来看
用CAS操作实现Go标准库中的Once的更多相关文章
- c/c++标准库中的文件操作总结
1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...
- STL笔记(6)标准库:标准库中的排序算法
STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...
- 彻底弄清c标准库中string.h里的常用函数用法
在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...
- 通过atomic_flag简单自旋锁实现简单说明标准库中锁使用的memory_order
在使用标准库中的加锁机制时,例如我们使用std::mutex,写了如下的代码(下面的代码使用condition_variable可能更合适) std::mutex g_mtx; int g_resNu ...
- php标准库中QplQueue队列如何使用?
php标准库中QplQueue队列如何使用? 一.总结 1.new对象,然后通过enqueue方法和dequeue方法使用. 二.php标准库中QplQueue队列如何使用? 队列这种数据结构更简单, ...
- stm32存储器映像和标准库中定义外设地址的方法
结合存储器映像理解stm32标准库中定义外设地址的方法. stm32f103zet6是32位的.它所能访问的地址空间范围为2^32=4GB,把4GB分为8个block,分别为block0-block- ...
- Python 标准库中的装饰器
题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...
- (转)python标准库中socket模块详解
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
- C标准库中atoi的一种可能的实现
为避免与标准库中的atoi产生歧义, 我将自己编写的函数命名为strToInt, 以下是示例代码 #include <stdio.h> int strToInt(const char *s ...
随机推荐
- 【windows核心编程】一个HOOK的例子
一.应用场景 封装一个OCX控件,该控件的作用是来播放一个视频文件,需要在一个进程中放置四个控件实例. 由于控件是提供给别人用的,因此需要考虑很多东西. 二.考虑因素 1.控件的父窗口resize时需 ...
- 开通GitHub以及使用笔记
把小游戏的代码和博客迁移到GitHub上,路径是:https://github.com/GAMTEQ,欢迎访问 以下是使用GITHUB的一些命令 504 cd code 506 mkdir Fai ...
- 10款jquery图片广告特效的预览及源码下载 改自[帅的相对论]
原文格式有问题,我来排版了一下,分享给大家. 1.jQuery仿海尔官网全屏焦点图特效代码 Query仿海尔官网全屏焦点图特效代码,带有左右箭头的jQuery焦点图切换特效.当焦点图切换时,下方的三块 ...
- 【和我一起学python吧】python的数据类型
python的元组.列表.字典数据类型是很python(there python is a adjective )的数据结构.这些结构都是经过足够优化后的,所以如果使用好的话,在某些area会有很大的 ...
- HDU-4749 Parade Show KMP算法 | DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题意:给两个串S和P,求S串中存在多少个与P串的大小关系一样的串. 因为数字的范围是1<= ...
- PhoneGap搭建运行环境(3.2版本)
一. 1.准备环境nodejs(http://nodejs.org/download/) 2.ant(http://ant.apache.org/bindownload.cgi) 3.Android ...
- Android 用MediaCodec实现视频硬解码(转)
本文向你讲述如何用android标准的API (MediaCodec)实现视频的硬件编解码.例程将从摄像头采集视频开始,然后进行H264编码,再解码,然后显示.我将尽量讲得简短而清晰,不展示 那些不相 ...
- canvas绘制清晰的方法
很早就开始使用canvas,包括自己绘制各种图形,以及作为画布提供给诸如echarts,当canvas绘制细线条,特别是关于文字绘制会出现很模糊或者锯齿的感觉. <canvas ref=&quo ...
- HDU 5734 Acperience (推导)
Acperience 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5734 Description Deep neural networks (DN ...
- IMAQ Flatten Image to String VI的参数设置对比
无压缩 jpeg压缩 无损二元包装 仅JPEG压缩时有效 平化类型(指定字符串中存储什么类型的数据) None JPEG PACKED BINARY Quality Image Image and ...