ホームページ  >  記事  >  バックエンド開発  >  golang アトミック置換

golang アトミック置換

王林
王林オリジナル
2023-05-16 10:28:37474ブラウズ

Golang は Google が開発したプログラミング言語で、同時プログラミングにおいて非常に強力な機能を備えています。その 1 つはアトミック操作で、マルチスレッド環境における共有リソースの正確性を保証します。 Golang では sync/atomic パッケージによってアトミックな操作が提供されていますが、この記事ではアトミックな置換操作について詳しく紹介します。

アトミック置換を紹介する前に、まずアトミック操作とは何かを理解しましょう。マルチスレッド プログラミングでは、複数のスレッドが共有リソースに同時にアクセスする必要がある場合、アクセスが調整されていないと、いくつかの問題が発生します。たとえば、複数のスレッドが同時に同じ値を変更しようとすると、競合状態が発生し、プログラム エラーや予期しない動作が発生する可能性があります。

この問題を解決するには、アトミック操作と呼ばれる手法を使用できます。アトミック操作は、実行中に中断したり変更したりすることができない分割不可能な操作です。これにより、複数のスレッドが共有リソースに同時にアクセスすることによって引き起こされる競合状態が回避されます。 Golang は、AddInt32、AddInt64、CompareAndSwapInt32 などのいくつかのアトミック操作関数を提供します。

アトミック置換操作関数は、SwapInt32、SwapInt64、SwapUint32、SwapUint64、および SwapPointer です。 SwapInt32 を例にとると、その関数プロトタイプは次のとおりです。

func SwapInt32(addr *int32, new int32) (old int32)

この関数は、int32 型変数へのポインタを受け取り、 new int32 値。ポインタが指すメモリ アドレスの値を新しい値に置き換えて、元の値を返そうとします。同時変更により置換が失敗した場合は、元の値が返されます。この関数はアトミックなので、複数のスレッドが同時に SwapInt32 を呼び出して同じ値を変更しても問題はありません。

簡単な例を見てみましょう。この例のカウンターは int32 型の変数であり、複数のスレッドがその値を同時に 1 増加させようとします。アトミック置換操作を使用しない場合は、ロックを使用して、複数のスレッドが同時にカウンターを変更しないようにする必要があります。これにより、パフォーマンスの低下が発生します。アトミック置換操作では、ロックは必要ありません。コードは次のとおりです。

package main

import (
    "fmt"
    "sync/atomic"
    "time"
)

func main() {
    var counter int32
    
    for i := 1; i <= 10; i++ {
        go func() {
            for {
                oldValue := atomic.LoadInt32(&counter)
                if atomic.CompareAndSwapInt32(&counter, oldValue, oldValue+1) {
                    break
                }
                time.Sleep(time.Millisecond)
            }
        }()
    }
    
    time.Sleep(time.Second * 1)
    
    fmt.Println(counter)
}

この例では、カウンターの初期値を 0 に設定し、10 個のゴルーチンを開始してそれに 1 を加えます。各ゴルーチンでは、for ループを使用して、カウンター値を 1 ずつ継続的にインクリメントしようとします。ここでは、LoadInt32 関数を使用してカウンター値を読み取り、CompareAndSwapInt32 関数を使用してアトミック置換操作を実行します。ここでは、oldValue が比較の基準値として使用され、現在のカウンタの値が oldValue と同じである場合、アトミックな置換操作が実行されます。置換が成功した場合はループを終了し、置換が失敗した場合は、しばらく待ってから再試行します。

この例では、複数のゴルーチンがカウンターの値を同時に k として読み取り、それを同時に 1 ずつ増加させ、カウンターが 1 だけ増加するという競合状態が考えられます。ただし、アトミックな置換操作を使用しているため、各 goroutine はカウンタを変更しようとするときにのみ動作し、他のスレッドはカウンタを変更できないため、競合状態は発生しません。プログラムによって出力される最終的なカウンター値は 10 になるはずで、結果は一般に次のようになります。

この記事では、SwapInt32、SwapInt64、SwapUint32、SwapUint64、SwapPointer など、Golang のアトミック置換操作関数を紹介します。アトミック操作は、マルチスレッド プログラミングにおける共有リソースの正確性を確保するための重要な手段であり、競合状態を回避できます。 Golang には、スピン ロックや CAS 操作などの機能を実装するためのアトミック操作関数がいくつか用意されており、プログラマは適切なアトミック操作関数を選択して、並行プログラミングの問題を解決できます。

以上がgolang アトミック置換の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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