1. 使用互斥锁(Mutex)
    互斥锁(Mutex)是一种常用的同步原语,用于防止多个协程同时访问共享资源。

    package main
    import (
     "fmt"
     "sync"
    )
    var (
     counter int
     mutex   sync.Mutex
    )
    func increment(wg *sync.WaitGroup) {
     defer wg.Done()
     mutex.Lock()
     counter++
     mutex.Unlock()
    }
    func main() {
     var wg sync.WaitGroup
     for i := 0; i < 1000; i++ {
         wg.Add(1)
         go increment(&wg)
     }
     wg.Wait()
     fmt.Println("Final Counter:", counter)
    }
  2. 使用channel
    Go语言的核心理念之一就是“不通过共享内存来通信,而是通过通信来共享内存”。我们可以通过创建一个channel,然后通过发送和接收消息的方式来读写共享变量。这种方式在处理并发问题时非常有用,因为channel本身就提供了安全性。

    package main
    import (
     "fmt"
    )
    func increment(counter chan int, done chan bool) {
     for i := 0; i < 1000; i++ {
         value := <-counter
         value++
         counter <- value
     }
     done <- true
    }
    func main() {
     counter := make(chan int, 1)
     counter <- 0
     done := make(chan bool)
     for i := 0; i < 10; i++ {
         go increment(counter, done)
     }
     for i := 0; i < 10; i++ {
         <-done
     }
     fmt.Println("Final Counter:", <-counter)
    }
  3. 读写锁(sync.RWMutex)
    如果程序中的读操作远多于写操作,那么使用读写锁可能会比互斥锁更有效率。读写锁允许多个协程同时读取变量,但是只允许同一时刻只有一个协程进行写入操作。
package main
import (
    "fmt"
    "sync"
)
var (
    counter int
    rwMutex sync.RWMutex
)
func read(wg *sync.WaitGroup) {
    defer wg.Done()
    rwMutex.RLock()
    fmt.Println("Counter:", counter)
    rwMutex.RUnlock()
}
func write(wg *sync.WaitGroup) {
    defer wg.Done()
    rwMutex.Lock()
    counter++
    rwMutex.Unlock()
}
func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go read(&wg)
    }
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go write(&wg)
    }
    wg.Wait()
}
  1. 原子操作(sync/atomic包)
    对于一些简单的数值或者布尔类型,我们可以使用原子操作来读写共享变量。

    package main
    import (
     "fmt"
     "sync"
     "sync/atomic"
    )
    var counter int64
    func increment(wg *sync.WaitGroup) {
     defer wg.Done()
     atomic.AddInt64(&counter, 1)
    }
    func main() {
     var wg sync.WaitGroup
     for i := 0; i < 1000; i++ {
         wg.Add(1)
         go increment(&wg)
     }
     wg.Wait()
     fmt.Println("Final Counter:", counter)
    }
  2. sync.Once
    如果共享变量只需要被初始化一次,可以使用sync.Once来确保初始化的并发安全性。

    package main
    import (
     "fmt"
     "sync"
    )
    var (
     once sync.Once
     initValue int
    )
    func initialize() {
     fmt.Println("Initializing...")
     initValue = 42
    }
    func doSomething() {
     once.Do(initialize)
     fmt.Println("Value:", initValue)
    }
    func main() {
     var wg sync.WaitGroup
     for i := 0; i < 10; i++ {
         wg.Add(1)
         go func() {
             defer wg.Done()
             doSomething()
         }()
     }
     wg.Wait()
    }

cyp3x6rl
1 声望0 粉丝