非リエントラント関数とは、呼び出された回数やゴルーチンの数に関係なく、一度に 1 回しか実行できない関数です。
特定のサービスは、特定の条件をポーリングし、特定のステータスを毎秒監視します。各状態をブロックせずに個別にチェックできるようにしたいと考えています。
実装は次のようになります: (推奨学習: Go )
func main() { tick := time.Tick(time.Second) go func() { for range tick { go CheckSomeStatus() go CheckAnotherStatus() } }() }
goroutine のステータス チェックで、every を実行することを選択します。そのため、CheckAnotherStatus() は CheckSomeStatus() が完了するまで待機しません。
各チェックにかかる時間は通常、1 秒にも満たない短い時間です。しかし、CheckAnotherStatus() 自体の実行に 1 秒以上かかる場合はどうなるのでしょうか?予期しないネットワークまたはディスクの遅延が発生し、チェックの実行時間に影響を与える可能性があります。
関数を同時に 2 回実行するのは意味がありますか?そうでない場合は、非再入可能にする必要があります。
ブロッキング、非再入可能関数
関数が複数回実行されるのを防ぐ簡単な方法は、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()」の実行中にストールが発生すると、後続の反復で同じ関数を呼び出すリクエストが発生します。
Yield、非再入可能関数
ステータス チェックのストーリーで、次の 10 回の呼び出しを積み上げるのはおそらく意味がありません。停止した CheckAnotherStatus() の実行が完了すると、10 個の呼び出しすべてが突然順番に実行され、次の 1 秒以内に完了する可能性があり、同じ秒内に 10 個の同一のチェックが完了します。
もう一つの解決策は降伏することです。有益な解決策は次のとおりです。
「CheckAnotherStatus()」がすでに実行されている場合は、その実行を中止します。
「CheckAnotherStatus()」の実行は最大 1 回のみ実行されます。
ループの反復回数に比べて、実際に実行される「CheckAnotherStatus()」の呼び出しの数は少なくなる可能性があります。
以上がGolang の非リエントラント関数の実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。