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()
}
4. 原子操作(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)
}
5. 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()
}
最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB