Go 関数の同時実行安全性とは、同時にデータにアクセスする複数の goroutine によって引き起こされる損傷を避けるために、関数が同時に呼び出された場合でも正しく動作できることを意味します。同時実行安全な関数では、ロック、チャネル、アトミック変数などのメソッドを使用できます。ロックにより、ゴルーチンは重要なセクションに排他的にアクセスできるようになり、チャネルは安全な通信メカニズムを提供し、アトミック変数は特定の変数への同時安全なアクセスを提供します。実際のケースでは、チャネルを使用して同時実行安全機能を実装し、複数のゴルーチンが共有リソースに正しい順序でアクセスできるようにします。
Go では、同時実行安全性とは、関数が同時に呼び出されたときにも正しく動作できることを保証することを指します。言い換えれば、関数は、複数のゴルーチンからの同時アクセスによって内部状態が破損しないことを保証する必要があります。
次は、同時実行性が安全でない関数の例です。
var counter int func IncrementCounter() { counter++ }
counter
が次のように宣言されている場合でも、 atomic
Integer、counter
へのアクセスを保護する同期メカニズムがないため、この関数はまだ安全ではありません。これは、複数のゴルーチンが同時に counter
をインクリメントしようとし、データ競合を引き起こす可能性があることを意味します。
同時実行性が安全な関数を作成するには、いくつかの異なる方法を使用できます。
1. ロックの使用
Lock は、Goroutine がクリティカル セクション (共有リソースにアクセスするコード セグメント) に入る前にロックを取得できるようにする同期メカニズムです。 goroutine がロックを取得すると、クリティカル セクションに排他的にアクセスできるようになります。例:
var mu sync.Mutex func IncrementCounter() { mu.Lock() defer mu.Unlock() counter++ }
2. チャネルの使用
チャネルは、ゴルーチン間の安全な通信のためのメカニズムです。チャネルは、メッセージを渡したり、ゴルーチンの実行を同期したりするために使用できます。例:
var incrementChan = make(chan struct{}) func IncrementCounter() { incrementChan <- struct{}{} <-incrementChan counter++ }
3. アトミック変数の使用
アトミック変数は、変数への同時安全なアクセスを提供する特別なタイプの変数です。 Go 言語には、次のようないくつかの組み込みアトミック変数が用意されています。
import "sync/atomic" var counter int64 func IncrementCounter() { atomic.AddInt64(&counter, 1) }
次に、チャネルを使用して同時安全機能を実装する実際的なケースを示します。
package main import ( "fmt" "sync" ) var wg sync.WaitGroup func main() { ch := make(chan struct{}) for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() <-ch fmt.Println("Goroutine:", i) }() } close(ch) wg.Wait() }
このプログラムでは 100 個のゴルーチンが作成され、各ゴルーチンはチャネル ch
からメッセージを受け取ります。チャネルが閉じられると、すべてのゴルーチンが起動され、それらの ID が正しい順序で出力されます。
チャネルを使用することで、ゴルーチンが共有リソース (チャネルなど) に同時にアクセスしないようにすることができ、それによって同時実行の安全性を実現できます。
以上がgolang 関数の同時実行の安全性の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。