以太坊系列之四: 使用atomic来避免lock
使用atomic来避免lock
在程序中为了互斥,难免要用锁,有些时候可以通过使用atomic来避免锁,
从而更高效.
下面给出一个以太坊中的例子,就是MsgPipeRW,从名字Pipe可以看出,
他实际上就是一个pipe,相比大家对pipe已经比较熟悉了,我就不多解释了.
type MsgPipeRW struct {
w chan<- Msg
r <-chan Msg
closing chan struct{}
closed *int32
}
//创建一个MsgPipeRw
func MsgPipe() (*MsgPipeRW, *MsgPipeRW) {
var (
c1, c2 = make(chan Msg), make(chan Msg)
closing = make(chan struct{})
closed = new(int32)
rw1 = &MsgPipeRW{c1, c2, closing, closed}
rw2 = &MsgPipeRW{c2, c1, closing, closed}
)
return rw1, rw2
}
pipe就像水管一样,这里MsgPipe创建了两根水管,可以自由双向流动,rw1写,rw2就可以
读到,rw2写,rw1就可以读到.原理也很简单,因为rw1写和rw2操作的是同一个chan Msg,反之亦然.
关键是这里的closed,可以想想rw1,rw2很有可能在不同的goroutine发生读写关闭等操作,
这时候要同时访问closed这个变量,难免会发生冲突,我们看看如何避免.
closed如果为0表示没有关闭,1表示已经关闭,就不应该再进行读写了.
// 从pipe中读取一个msg
func (p *MsgPipeRW) ReadMsg() (Msg, error) {
//这里不能直接*p.closed==0,要使用atomic.LoadInt32来访问
if atomic.LoadInt32(p.closed) == 0 {
...
}
return Msg{}, ErrPipeClosed
}
// 写的时候也一样
func (p *MsgPipeRW) WriteMsg(msg Msg) error {
if atomic.LoadInt32(p.closed) == 0 {
...
}
return ErrPipeClosed
}
读写消息只是读取互斥变量,没有发生写入,下面来看看close的时候如何写入
func (p *MsgPipeRW) Close() error {
if atomic.AddInt32(p.closed, 1) != 1 { //避免锁,
// someone else is already closing
atomic.StoreInt32(p.closed, 1) // avoid overflow
return nil
}
close(p.closing)
return nil
}
atomic.AddInt32能够避免我们一般这样的写法发生的并发访问.
if *p.closed==0 {
*p.closed+=1
}
感兴趣的可以修改代码试试,采用*p.closed==0这种方式,会不会造成崩溃,测试代码如下
func TestMsgPipeConcurrentClose(t *testing.T) {
rw1, _ := MsgPipe()
for i := 0; i < 10; i++ {
go rw1.Close()
}
}
atomic看似神奇的避免了锁,实际上这需要处理器的特殊指令支持,尤其是发生在多和处理器上时,atomic指令
会保证对特定地址的锁定.
atomic相对于lock的最大优势就是他只是一条特殊指令,不用发生系统上下文切换,我们都知道系统上下文切换
代价要大得多.
以太坊系列之四: 使用atomic来避免lock的更多相关文章
- 以太坊系列之十六: 使用golang与智能合约进行交互
以太坊系列之十六: 使用golang与智能合约进行交互 以太坊系列之十六: 使用golang与智能合约进行交互 此例子的目录结构 token contract 智能合约的golang wrapper ...
- 以太坊系列之十七: 使用web3进行合约部署调用以及监听
以太坊系列之十七: 使用web3进行智能合约的部署调用以及监听事件(Event) 上一篇介绍了使用golang进行智能合约的部署以及调用,但是使用go语言最大的一个问题是没法持续监听事件的发生. 比如 ...
- 以太坊系列之十六:golang进行智能合约开发
以太坊系列之十六: 使用golang与智能合约进行交互 以太坊系列之十六: 使用golang与智能合约进行交互 此例子的目录结构 token contract 智能合约的golang wrapper ...
- 以太坊系列之一: 以太坊RLP用法-以太坊源码学习
RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式.RLP的唯一目标就是解决结构体的编码问题:对原子数据类型(比如,字符串,整数型, ...
- 以太坊系列之十八: 百行go代码构建p2p聊天室
百行go代码构建p2p聊天室 百行go代码构建p2p聊天室 1. 上手使用 2. whisper 原理 3. 源码解读 3.1 参数说明 3.1 连接主节点 3.2 我的标识 3.2 配置我的节点 3 ...
- 以太坊系列之六: p2p模块--以太坊源码学习
p2p模块 p2p模块对外暴露了Server关键结构,帮助上层管理复杂的p2p网路,使其集中于Protocol的实现,只关注于数据的传输. Server使用discover模块,在指定的UDP端口管理 ...
- 以太坊系列之三: 以太坊的crypto模块--以太坊源码学习
以太坊的crypto模块 该模块分为两个部分一个是实现sha3,一个是实现secp256k1(这也是比特币中使用的签名算法). 需要说明的是secp256k1有两种实现方式,一种是依赖libsecp2 ...
- 以太坊系列之二: 单调时间monotime-以太坊源码学习
在程序中需要测量时间时最好使用monotime.Now()而不是time.Now(),相比之下前者更准确. 来个示例: func main() { var start, elapsed time.Du ...
- 以太坊系列之十一: 零起步使用remix开发智能合约
一步一步使用remix开发智能合约 最新版的remix(2017-8-3)只能使用在线开发了,已经没有离线版本了,并且好像在线版本要FQ才能访问(自行解决). 1.打开remix 注意地址如果是htt ...
随机推荐
- Effective java笔记3--类和接口2
三.接口优于抽象类 java提供两种机制,可以用来定义一个允许多个实现的类型:接口和抽象类.由于java只允许单继承,所以,抽象类作为类型定义受到了极大的限制. 已有的类可以很容易被更新,以实现新的接 ...
- Spring Batch介绍
简介 SpringBatch 是一个大数据量的并行处理框架.通常用于数据的离线迁移,和数据处理,⽀持事务.并发.流程.监控.纵向和横向扩展,提供统⼀的接⼝管理和任务管理;SpringBatch是Spr ...
- 迭代器-迭代对象-dir(a)可以查看该数据类型有多少种方法。range(10)在py3里就是一个迭代器,for循环实际就是迭代器的应用
迭代器 我们已经知道,可以直接作用于for循环的数据烈性有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str,bytes等: 一类是generator,数据结构,包括生成 ...
- python学习(四) 字典:当索引不好用时
第四章 字典:当索引不好用时 4.1 字典的使用 字典的适用场景: 表示一个游戏棋盘的状态,每个键都是由坐标值组成的元组: 存储文件修改时间,用文件名作为键: 数字电话/地址簿 4.2 创建和使用字典 ...
- Unable to find required classes (javax.activation.DataHandler and javax.mail.internet.MimeMultipart)
在接触WebService时值得收藏的一篇文章: 在调试Axis1.4访问WebService服务时,出现以下错误: Unable to find required classes (javax.ac ...
- linux进行Java开发环境的部署
一.前言: 今天正式向linux开发进攻了,其中遇到一些问题简单的记录一下,为之后的再次部署提供方便. 二.linux的Java8安装的两种方法: 1.源安装很简单,一个命令搞定. sudo apt- ...
- POJ1657
1.题目链接地址 http://poj.org/problem?id=1657 2.源代码 #include<iostream> using namespace std; int main ...
- Java多线程-新特征-阻塞栈LinkedBlockingDeque
对于阻塞栈,与阻塞队列相似.不同点在于栈是“后入先出”的结构,每次操作的是栈顶,而队列是“先进先出”的结构,每次操作的是队列头. 这里要特别说明一点的是,阻塞栈是Java6的新特征.. Java为阻塞 ...
- Linux常用基本命令 1
useradd 创建用户. password 修改密码. date 查看时间 man date 帮助文档.f往后翻 b往前翻 q退出.软修改 man hwclock 修改硬件时钟, cal 查看日历 ...
- jsoup 的简单应用
导入相关jar包 package jsoup.zr.com.utils; import java.io.IOException; import java.util.List; import org.j ...