ホームページ >バックエンド開発 >Golang >Golangでの同期方法を紹介した記事

Golangでの同期方法を紹介した記事

PHPz
PHPzオリジナル
2023-04-14 10:31:26994ブラウズ

Golang は同時プログラミングをサポートする言語ですが、同時プログラミングではデータの不整合が発生しやすくなります。したがって、Golang では、プログラムの正確性と信頼性を確保するために同期方法を使用する必要があります。この記事ではGolangでの同期方法を紹介します。

1. ミューテックス ロック

ミューテックス ロックは、最も一般的に使用される同期メカニズムです。ミューテックス ロックを通じて共有リソースをロックし、同時に 1 つのスレッドのみがリソースにアクセスできるようにすることができます。リソースにより競合状態の発生が回避されます。 Golang では、ミューテックス ロックは標準ライブラリの sync.Mutex を通じて実装されます。次に、ミューテックス ロックのサンプル コードを示します。

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var lock sync.Mutex
    var wg sync.WaitGroup

    var count int

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            lock.Lock() // 加锁
            defer lock.Unlock() // 解锁

            count++
            time.Sleep(time.Second)
            fmt.Println(count)
            wg.Done()
        }()
    }

    wg.Wait()
}

2. 読み取り/書き込みロック

読み取り/書き込みロックは、複数のスレッドが共有リソースにアクセスできるようにする特別なミューテックス ロックです。読み取り操作は可能ですが、書き込み操作中は 1 つのスレッドのみが共有リソースに同時にアクセスできます。 Golang では、読み取り/書き込みロックは標準ライブラリの sync.RWMutex を通じて実装されます。以下は、読み取り/書き込みロックのサンプル コードです:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var lock sync.RWMutex
    var wg sync.WaitGroup

    var count int

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(idx int) {
            // 多个线程读操作可以同时进行
            lock.RLock()
            fmt.Printf("读协程%d,count=%d\n", idx, count)
            lock.RUnlock()

            // 一个线程写操作时,其它线程无法读写
            lock.Lock()
            count++
            fmt.Printf("写协程%d,count=%d\n", idx, count)
            time.Sleep(time.Second)
            lock.Unlock()

            wg.Done()
        }(i)
    }

    wg.Wait()
}

3. 条件変数

条件変数は、スレッドが特定の条件に基づいて同期できるようにする同期メカニズムです。 Golang では、条件変数は標準ライブラリの sync.Cond を通じて実装されます。以下は条件変数のサンプル コードです:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var lock sync.Mutex
    var wg sync.WaitGroup
    var cond = sync.NewCond(&lock)

    done := false

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(idx int) {
            lock.Lock()
            for !done {
                cond.Wait() // 等待通知
            }
            fmt.Printf("协程%d收到通知\n", idx)
            lock.Unlock()

            wg.Done()
        }(i)
    }

    time.Sleep(time.Second)

    lock.Lock()
    done = true // 向所有协程发送通知
    cond.Broadcast()
    lock.Unlock()

    wg.Wait()
}

4. アトミック操作

アトミック操作は、ロックせずにメモリ データを読み書きできる操作です。 Golang では、アトミック操作は標準ライブラリの sync/atomic を通じて実装されます。以下はアトミック操作のサンプル コードです。

package main

import (
    "fmt"
    "sync/atomic"
)

func main() {
    var value int32
    atomic.StoreInt32(&value, 10)
    fmt.Println(atomic.LoadInt32(&value))

    atomic.AddInt32(&value, 5)
    fmt.Println(atomic.LoadInt32(&value))

    atomic.CompareAndSwapInt32(&value, 15, 20) // 如果value等于15,则将其更新为20
    fmt.Println(atomic.LoadInt32(&value))
}

ミューテックス ロック、読み取り/書き込みロック、条件変数、アトミック操作などの同期方法を通じて、Golang プログラムの正確性と信頼性を効果的に保証できます。

以上がGolangでの同期方法を紹介した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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