Home  >  Article  >  Backend Development  >  Golang non-reentrant function implementation

Golang non-reentrant function implementation

(*-*)浩
(*-*)浩Original
2019-12-17 13:53:132669browse

Golang non-reentrant function implementation

A non-reentrant function is a function that can only be executed once at any point in time, regardless of how many times it is called and how many goroutines there are.

A certain service polls certain conditions and monitors some status every second. We want each state to be checked independently without blocking.

Implementation may be like this: (Recommended Learning: Go )

func main() {
    tick := time.Tick(time.Second)     
    go func() {         
        for range tick {             
            go CheckSomeStatus()             
            go CheckAnotherStatus()         
        }     
    }() 
}

We choose to run every in our goroutine Status check so that CheckAnotherStatus() does not wait for CheckSomeStatus() to complete.

Each check usually takes a short time, much less than a second. But what happens if CheckAnotherStatus() itself takes more than a second to run? There may be an unexpected network or disk delay that affects the check execution time.

Does it make sense to execute a function twice at the same time? If not, we want it to be non-reentrant.

Blocking, non-reentrant functions

An easy way to prevent a function from running multiple times is to use sync.Mutex.

Assuming we only care about calling this function from the above loop, we can implement the lock from outside the function:

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()             
        }()         
       }     
     }() 
}

The above code guarantees CheckAnotherStatus() Not performed by multiple iterations of the loop. When CheckAnotherStatus() was previously executed, any subsequent iterations of the loop would be blocked by the mutex.

The blocking solution has the following properties:

It ensures that there are as many calls to "CheckAnotherStatus()" as the number of loop iterations.

Assuming a stall executing "CheckAnotherStatus()", subsequent iterations result in requests to call the same function.

Yield, non-reentrant function

It probably doesn't make sense to stack up for the next 10 calls in our status check story. A stalled CheckAnotherStatus() execution completes, all 10 calls suddenly execute, sequentially, and may be completed within the next second, with 10 identical checks completed in the same second.

Another solution is to surrender. A profitable solution is:

Abort execution of "CheckAnotherStatus()" if it has already been executed.

The execution of "CheckAnotherStatus()" will be run at most once.

Fewer calls to "CheckAnotherStatus()" may actually be run compared to the number of loop iterations.

The above is the detailed content of Golang non-reentrant function implementation. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn