golang使用通道模仿实现valatile语义
golang团队在sync中提供了很多的原子操作函数,将原子操作转向由单独一个包提供,而不是像Java那样提供各种累,确实上手得更加简单。但是golang原生提供的并发操作没有Java来得丰富,或者庞大(这里并不想展开语言相杀),只是笔者在练习的时候,想试着用golang实现类似Java中的valatile的语义功能,却发现golang没有提供类似的关键字,这个时候只能借助sync和sync/atmoic的同步语句来实现对应的功能。事实是,如果是借助锁的同步方式来实现对应的valatile语义,笔者认为大大浪费和误会了golang的设计协程的初衷,此时笔者想起了golang团队的一句话
勿以共享方式通信,以通信实现共享
为什么不试试用下通道,看看能不能达到类似的功能。valatile修饰的变量本身则是个共享变量,因此,我们的目标是用通信的方式实现对共享变量的修改。下面笔者以自定义session管理器作为例子展开说明。
StandardSession有个isValidChan属性,类型是一个chan bool,标志该session是否有效,但是同一时刻可能会有多个客户端对该session进行无效化操作,即isValidChan属性符合valatile的应用场景。
type StandardSession struct {
isValidChan chan bool
}
我们需要对isValidChan属性初始化为容量为1的通道,即make(chan bool, 1);isValidChan <- true,注意容易必须设置为1,而且必须发送默认值到通道中。接下来则是设计对该共享变量的读取和设置,以模仿volatila的语义。
这里需要说明两点知识点,一是容量为0的通道,通信是同步且无缓冲的:在有接受者接收数据之前,发送不会结束。可以想象一个无缓冲的通道在没有空间来保存数据的时候:必须要一个接收者准备好接收通道的数据然后发送者可以直接把数据发送给接收者。所以通道的发送/接收操作在对方准备好之前是阻塞的,二是,如果容量大于 0,通道就是异步的了:缓冲满载(发送)或变空(接收)之前通信不会阻塞,元素会按照发送的顺序被接收。如果容量是0或者未设置,通信仅在收发双方准备好的情况下才可以成功。以下的两个则是利用了这两个特点,设置通道的容量为1,当有一条协程接受该通道的值之后,通道的长度变为0,其他协程必须得阻塞等待该协程重新发送新的值到该通道之后,才能读取最新的值,即共享的值保存在通道中,同一时刻只有一条协程能够对该通道进行操作。
//实现对IsValid原子修改
func (session *StandardSession) SetIsValid(isValid bool) {
<-session.isValidChan
session.isValidChan <- isValid
}
//实现对IsValid原子读取
func (session *StandardSession) IsValid() bool {
b := <-session.isValidChan
session.isValidChan <- b
return b
}
这里本质上还是同步化以达到共享变量的即时更新,volatile的原理是不需要通过同步指令,针对CPU指令级别的,是通过强制更新处理器内存,刷新CPU缓存以达到即时更新。所以这里只能说是笔者作为练习的模仿实现,如若读者有更好的实现,不吝赐教。
简书地址:https://www.jianshu.com/p/4a4feb2c5590
golang使用通道模仿实现valatile语义的更多相关文章
- 【转】Golang 关于通道 Chan 详解
原文:http://blog.csdn.net/netdxy/article/details/54564436 在用 chan 类型时,发生死锁的错误,表面上看不出什么问题 ------------- ...
- [Go] golang缓冲通道实现资源池
go的pool资源池:1.当有多个并发请求的时候,比如需要查询数据库2.先创建一个2个容量的数据库连接资源池3.当一个请求过来的时候,去资源池里请求连接资源,肯定是空的就创建一个连接,执行查询,结束后 ...
- [Go] golang缓冲通道实现管理一组goroutine工作
通道1.当一个资源需要在goroutine之间共享时,通道在goroutine之间架起了一个管道2.无缓冲通道和有缓冲通道,make的第二个参数就是缓冲区大小3.无缓冲通道需要发送和接收都准备好,否则 ...
- 语义分割之Dual Attention Network for Scene Segmentation
Dual Attention Network for Scene Segmentation 在本文中,我们通过 基于自我约束机制捕获丰富的上下文依赖关系来解决场景分割任务. 与之前通过多尺 ...
- 再探go modules:使用与细节
还有半个月go1.12就要发布了.这是首个将go modules纳入正式支持的稳定版本. 距离go modules随着go1.11正式面向广大开发者进行体验也已经过去了半年,这段时间go module ...
- Dual Attention Network for Scene Segmentation
Dual Attention Network for Scene Segmentation 原始文档 https://www.yuque.com/lart/papers/onk4sn 在本文中,我们通 ...
- java并发编程基础-ReentrantLock及LinkedBlockingQueue源码分析
ReentrantLock是一个较为常用的锁对象.在上次分析的uil开源项目中也多次被用到,下面谈谈其概念和基本使用. 概念 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 相 ...
- 并发之AtomicInteger
并发之AtomicInteger 1 java.util.concurrent.atomic概要 在java.util.concurrent.atomic包下存在着18个类,其中Integer ...
- 《Stereo R-CNN based 3D Object Detection for Autonomous Driving》论文解读
论文链接:https://arxiv.org/pdf/1902.09738v2.pdf 这两个月忙着做实验 博客都有些荒废了,写篇用于3D检测的论文解读吧,有理解错误的地方,烦请有心人指正). 博客原 ...
随机推荐
- Cocos2D:塔防游戏制作之旅(十八)
在Enemy.m的getDamaged:方法只给你添加如下1行(在if条件内): [theGame awardGold:200]; 现在运行游戏你将注意到你不能放置超出你资源金币的炮塔了.当然杀死敌人 ...
- python安装json的方法;以及三种json库的区别
python中的json解释库有好几个,不同版本使用方法不同. 常用有 json-py 与smiplejson 两个包 其中,json-py 包含json.py外,还有一个minjson,两者用法上有 ...
- OC:打僵尸问题(类的问题)
1.定义普通僵尸类: 实例变量:僵尸种类.僵尸总血量.僵尸每次失血量. 方法:初始化方法(设置僵尸种类,总血量).被打击失血.死亡. 2.定义路障僵尸类: 实例变量:僵尸种类.僵尸总血量.僵尸每次失血 ...
- OC语言(七)Block复习
看下面一道Block的面试题: int i = 10; void(^myBlock)() = ^{ NSLog(@"%d",i); }; i = 100; myBlock(); 经 ...
- C++ Primer 有感(函数)
1.函数应该在头文件中声明,并在源文件中定义.(定义函数的源文件应包含声明该函数的头文件)将提供函数声明的头文件包含在定义该函数的源文件中,可使编译器能检查该函数的定义和声明是否一致. 2.既可以在函 ...
- 网站开发进阶(二十九)HTML特殊转义字符
HTML特殊转义字符 参考文献 http://tool.oschina.net/commons?type=2 美文美图
- Mahout系列之-----相似度
Mahout推荐系统中有许多相似度实现,这些组件实现了计算不能User之间或Item之间的相似度.对于数据量以及数据类型不同的数据源,需要不同的相似度计算方法来提高推荐性能,在mahout提供了大量用 ...
- 【一天一道LeetCode】#18. 4Sum
一天一道LeetCode (一)题目 Given an array S of n integers, are there elements a, b, c, and d in S such that ...
- 集团公司(嵌入ETL工具)财务报表系统解决方案
集团公司(嵌入ETL工具)财务报表系统解决方案 一.项目背景: 某集团公司是一家拥有100多家子公司的大型集团公司,旗下子公司涉及各行各业,包括:金矿.铜矿.房产.化纤等.由于子公司在业务上的差异,子 ...
- saiku中文查询(鉴于有人提问:saiku执行mdx,有中文报错)
有人问我saiku的中文查询问题: saiku默认执行英文,很多人,在mysql里录入了中文,使用sql语言查询没有问题. 可是,用saiku的mdx查询,就会报错. 这是因为mysql默认支持中文查 ...