0%

sync工具包介绍

sync.Once

专门用于确保某些初始化代码只被执行一次,不论该代码由多少个 goroutine 调用.

package main

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

func main() {
    var once sync.Once
    for i := 0; i < 10; i++ {
        go func() {
            // sync.Once 提供了一个方法 Do,这个方法接受一个函数作为参数,并确保该函数只会被执行一次
            once.Do(func() {
                fmt.Println("once")
            })
        }()
    }

    time.Sleep(1 * time.Second)
}

常用于单例模式,如

package main

import (
    "fmt"
    "sync"
)

type Singleton struct {
    // Fields for the singleton
}

var instance *Singleton
var once sync.Once

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{}
        fmt.Println("Singleton instance created")
    })
    return instance
}

sync.WaitGroup

WaitGroup 用于等待一组 goroutine 完成。可以增加计数器,并在 goroutine 完成时减少计数器

package main

import (
    "fmt"
    "sync"
)

func main() {
    var once sync.Once
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            once.Do(func() {
                fmt.Println("once")
            })
        }()
    }

    wg.Wait()
}

sync.Mutex

Mutex 是一个互斥锁,用于保护临界区,确保同一时间只有一个 goroutine 能够访问被保护的代码.

package main

import (
    "fmt"
    "sync"
)

var count int
var mutex sync.Mutex

// 通过Mutex解决线程安全问题
func Increase() {
    mutex.Lock()
    count++
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 500; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            Increase()
        }()
    }
    wg.Wait()
    fmt.Println(count)
}

sync.RWMutex

RWMutex 是一种读写互斥锁,允许多个读操作同时进行,但写操作会独占锁。

package main

import (
    "fmt"
    "sync"
)

var counter int
var rwMutex sync.RWMutex

func read() int {
    rwMutex.RLock()
    defer rwMutex.RUnlock()
    return counter
}

func write(val int) {
    rwMutex.Lock()
    counter = val
    rwMutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            write(i)
            fmt.Println("Read value:", read())
        }(i)
    }
    wg.Wait()
}