ホームページ >バックエンド開発 >Golang >Go でスレッド セーフを実現する方法: ミューテックス、アトミックス、またはチャネル?

Go でスレッド セーフを実現する方法: ミューテックス、アトミックス、またはチャネル?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-18 22:14:10308ブラウズ

How to Achieve Thread Safety in Go: Mutexes, Atomics, or Channels?

Go で変数のスレッドセーフを実装する方法

Java では、同期変数の概念により、単一のスレッドのみが実行できることが保証されますいつでも特定のコードブロック。ただし、Go は明示的な同期キーワードを提供しません。

根拠

Go は、「共有によって通信しない」という原則に基づいて、スレッド同期に対する異なるアプローチを推進しています。代わりに、コミュニケーションによって記憶を共有します。」これは、共有メモリへの直接アクセスを避け、チャネルなどの通信ベースのメカニズムを選択することを意味します。

ミューテックスベースの同期

ミューテックスが必要なシナリオに遭遇した場合、これを実装する方法は次のとおりです。 Go:

var (
    mu        sync.Mutex
    protectMe int
)

func getMe() int {
    mu.Lock()
    me := protectMe
    mu.Unlock()
    return me
}

func setMe(me int) {
    mu.Lock()
    protectMe = me
    mu.Unlock()
}

改善点

  • 同時読み取りアクセスを有効にするために、sync.Mutex を sync.RWMutex に変換します。
  • defer の使用を検討してください。エラーが発生した場合のリソース リークを避けるため。
  • コードの読みやすさと利便性を高めるために、保護された値内にミューテックスを追加します。

アトミック同期

単一の値を保護する必要がある場合は、sync/atomic の使用を検討してください。パッケージ:

var protectMe int32

func getMe() int32 {
    return atomic.LoadInt32(&protectMe)
}

func setMe(me int32) {
    atomic.StoreInt32(&protectMe, me)
}

通信ベースアプローチ

Go は、ゴルーチン間の通信にチャネルの使用を推奨し、共有変数の必要性を排除します。たとえば、パブリッシャー/サブスクライバー パターンの場合:

type topic struct {
    subscribing []chan int
}

var t = &topic{}

func subscribe() chan int {
    ch := make(chan int)
    t.subscribing = append(t.subscribing, ch)
    return ch
}

func publish(v int) {
    for _, ch := range t.subscribing {
        ch <- v
    }
}

このアプローチにより、メモリを共有せずにスレッドセーフな通信が保証されます。

以上がGo でスレッド セーフを実現する方法: ミューテックス、アトミックス、またはチャネル?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。