Golang之不可重入函数实现
女主宣言
一个不可重入的函数就是一个在任何时间点只能执行一次的函数,不管它被调用了多少次,以及有多少goroutines。
PS:丰富的一线技术、多元化的表现形式,尽在“HULK一线技术杂谈”,点关注哦!
一个不可重入的函数就是一个在任何时间点只能执行一次的函数,不管它被调用了多少次,以及有多少goroutines。
本篇文章说明了阻塞不可重入函数,并在golang中产生不可重入的函数实现。
场景用例
某个服务是对某些条件进行轮询,每秒监视一些状态。我们希望每个状态都可以独立地检查,而不需要阻塞。实现可能是这样的:
func main() { tick := time.Tick(time.Second)go func() {for range tick {go CheckSomeStatus()go CheckAnotherStatus()}}()
}
我们选择在自己的goroutine中运行每个状态检查,以便 CheckAnotherStatus() 不会等待 CheckSomeStatus() 完成。
每一项检查通常都要花费很短的时间,而且比一秒要少得多。但是,如果 CheckAnotherStatus() 本身需要超过一秒的时间运行,会发生什么呢?可能会有一个意外的网络或磁盘延迟影响检查的执行时间。
在同一时间执行两次的函数是否有意义?如果没有,我们希望它是不可重入的。
阻塞,不可重入函数
防止函数多次运行的简单方法是使用sync.Mutex。
假设我们只关心从上面的循环调用这个函数,我们可以从函数外面实现锁:
import ("sync""time"
)
func main() { tick := time.Tick(time.Second)var mu sync.Mutexgo func() {for range tick {go CheckSomeStatus()go func() {mu.Lock()defer mu.Unlock() CheckAnotherStatus()}()}}()
}
上面的代码保证了 CheckAnotherStatus() 不是由循环的多次迭代执行的。在以前执行 CheckAnotherStatus() 的时候,循环的任何后续迭代都会被互斥锁阻塞。
阻塞解决方案具有以下属性:
它确保了许多“CheckAnotherStatus()”的调用作为循环迭代的次数。
假设一个执行“CheckAnotherStatus()”的停顿,随后的迭代会导致请求调用相同函数的请求。
屈服,不可重入函数
在我们的状态检查故事中,对随后的10个电话堆积起来可能没有意义。一个停滞不前的 CheckAnotherStatus() 执行完成了,所有10个调用突然执行,顺序,并且可能在接下来的一秒内完成,在同一秒内完成10个相同的检查。
另一个解决办法是屈服。一个有收益的解决方案是:
如果已经执行了“CheckAnotherStatus()”的中止执行。
将最多运行一次“CheckAnotherStatus()”的执行。
与循环迭代的次数相比,实际上可能运行的“CheckAnotherStatus()”的调用更少。
解决方案是通过以下方式实现的:
import ( "sync/atomic""time")
func main() {tick := time.Tick(time.Second) var reentranceFlag int64go func() { for range tick { go CheckSomeStatus()go func() { if atomic.CompareAndSwapInt64(&reentranceFlag, 0, 1) {defer atomic.StoreInt64(&reentranceFlag, 0)} else { return}CheckAnotherStatus()}()}}()
}
atomic.compareandswapint64(&reentranceFlag, 0, 1) 只有在 reentranceFlag==0 时才会返回true,并将原子性地设置为1。在这种情况下,允许进入,并且可以执行该函数。reentranceFlag保持在1,直到 CheckAnotherStatus() 完成,此时它被重置。当 CompareAndSwapInt64(...) 返回false时,这意味着reentranceFlag!=0,这意味着该函数已经由另一个goroutine执行。代码产生并静默地退出函数。
总结
我们选择在问题的函数之外实现不可重入的代码;我们可以在函数本身中实现它。另外,对于 int64 而言,int32当然也足够用。以上就是本篇的内容,大家有什么疑问可以在文章下面留言沟通。
HULK一线技术杂谈
由360云平台团队打造的技术分享公众号,内容涉及云计算、数据库、大数据、监控、泛前端、自动化测试等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享
Golang之不可重入函数实现相关推荐
- 什么是可重入函数和不可重入函数
可重入函数 在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预料 ...
- 线程安全与可重入函数的区别及联系
一.线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 或者 ...
- Linux中的可重入函数和不可重入函数
可重入函数 可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏.可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失. 可重入函数使用的 ...
- 可重入函数、不可重入函数,注意事项
1.定义可重入函数,函数内不能含有全局变量及static变量,不能使用malloc.free 2.信号捕捉函数应设计为可重入函数 3.信号处理程序可以调用的可重入函数可参阅 man 7 signal ...
- 可重入函数与不可重入函数(转)
转自:http://www.cppblog.com/franksunny/archive/2007/08/03/29269.html 主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数 ...
- 14.线程安全?线程不安全?可重入函数?不可重入函数?
线程安全问题 基本定义 线程安全:简单来说线程安全就是多个线程并发执行同一段代码时,不会出现不同的结果,我们就可以说该线程是安全的: 线程不安全:如果多线程并发执行时会产生不同的结果,则该线程就是不安 ...
- UNIX再学习 -- 可重入函数和 SIGCHLD 语义
一.可重入函数 参与信号处理的函数必须是可重入函数. 1.何为重入? 假设进程的住控制流程此刻正在调用 foo 函数,就在 foo 函数刚执行到一半的时候,内核向进程递送了信号 a:假设进程对信号 a ...
- 2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,
1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL 默 ...
- 【Linux系统编程】可重入和不可重入函数
00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...
最新文章
- c detail of macro
- 编译时异常和运行时异常的区别
- sublime配置攻略
- android手机如何安装apk文件,如何安装APK文件到自己的android手机里?.doc
- CF643F-Bears and Juice【组合数学】
- LeetCode 1353. 最多可以参加的会议数目(排序+贪心,优先队列,难)
- k8s 集群居然可以图形化安装了?
- python3-开发进阶补充Django中的文件的上传
- WEB消息提醒实现之二 实现方式-Jquery Ajax长轮询
- mpc 安全多方计算协议_HashKey:说透安全多方计算 MPC 技术方案、挑战与未来
- 潭州课堂25班:Ph201805201 tornado 项目 第八课 增加喜欢功能(课堂笔记)
- java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/Str
- 处置Linux下Oracle Tomcat 8080端口辩说
- std::sort使用
- idea 调节背景护眼_IDEA 护眼色设置 背景行颜色取消等设置
- 微信小程序:升级版手机检测微信工具小程序源码
- CiteSpace学习笔记(四)——功能区和参数区
- 如何从零开始学习软件测试
- 螺旋传动设计系统lisp_螺旋传动设计
- linux系统下查看cpu功耗,Linux系统下查看CPU信息
热门文章
- 美次债危机负面效应正扩大到消费市场
- Spark GraphX算法 - Aggregate Messages (aggregateMessages)算法
- 实现option上下移动_JS实现Select的option上下移动的方法
- java作业不能运行_从Windows运行时,YARN作业失败
- binlog日志_mysql的binlog日志的自动定时清理
- 大兴新年大集 推10条文化旅游线
- Asp.Net前台调用后台变量
- js处理倒计时,日期可以是当前日期也可以传1个时间点
- 《算法导论》读书笔记之第9章 中位数和顺序统计学
- Calypso - Android和Evolution下的CalDAV/CardDAV/Web...