一个不可重入的函数就是一个在任何时间点只能执行一次的函数,不管它被调用了多少次,以及有多少goroutines。

某个服务是对某些条件进行轮询,每秒监视一些状态。我们希望每个状态都可以独立地检查,而不需要阻塞。

实现可能是这样的: (推荐学习:go)

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.Mutex         go 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()”的调用更少。

更多相关文章

  1. golang的函数怎么写
  2. 从go语言闭包谈函数式编程
  3. go语言中函数与方法介绍
  4. go语言结构体组合函数介绍
  5. golang如何调用函数?
  6. 详解Golang中函数作为值与类型
  7. go语言中普通函数与方法的区别是什么?
  8. 详解Go 中方法与函数的区别
  9. 关于golang封装一个bash函数,用于执行bash命令

随机推荐

  1. Linux网络设备驱动架構學習(三)
  2. 一·创建Linux服务器(基于阿里云)
  3. Linux中动态链接库总结
  4. Linux工程实践学习笔记——基于主机系统
  5. linux 内核模块学习
  6. Linux内核中的container_of函数简要介绍
  7. linux环境安装node.js环境和pm2
  8. Linux网络编程-客户端与服务器端通信(Ech
  9. 守护进程的单实例实现
  10. 【Linux_Shell 脚本编程学习笔记五、Orac