探索Go语言的并发控制:深入sync包
发表时间: 2024-05-23 11:43
sync包提供了基本的同步基元, 如互斥锁。除了Once和WaitGroup类型, 大部分都是适用于低水平程序线程, 高水平的同步使用channel通信更好一些。
atomic/atomic.go
package mainimport ( "fmt" "time")type atomicInt intfunc (a *atomicInt) increment() { *a++}func (a *atomicInt) get() int { return int(*a)}func main() { var a atomicInt a.increment() go func() { a.increment() }() time.Sleep(time.Millisecond) fmt.Println(a)}
D:\project\src\xiangmu6\atomic>go run atomic.go2D:\project\src\xiangmu6\atomic>go run -race atomic.go==================WARNING: DATA RACERead at 0x00c0000100a0 by main goroutine:main.main()D:/project/src/xiangmu6/atomic/atomic.go:25 +0xccPrevious write at 0x00c0000100a0 by goroutine 7:main.main.func1()D:/project/src/xiangmu6/atomic/atomic.go:11 +0x58Goroutine 7 (finished) created at:main.main()D:/project/src/xiangmu6/atomic/atomic.go:21 +0xb1==================2Found 1 data race(s)exit status 66
Go race condition以及解决方法
形成条件
一般情况下是由于在没有加锁的情况下多个协程进行操作对同一个变量操作形成竞争条件.
解决方式
方式1:使用互斥锁sync.Mutex
方式2:使用管道
使用管道的效率要比互斥锁高, 也符合Go语言的设计思想.
解决方法: 使用互斥锁sync.Mutex
package mainimport ( "fmt" "sync" "time")type atomicInt struct { value int lock sync.Mutex //Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。}func (a *atomicInt) increment() { /* a.lock.Lock() //Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。 defer a.lock.Unlock() //Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。 a.value++ */ fmt.Println("safe increment") func() { a.lock.Lock() defer a.lock.Unlock() a.value++ }()}func (a *atomicInt) get() int { a.lock.Lock() //Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。 defer a.lock.Unlock() //Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。 return a.value}func main() { var a atomicInt a.increment() go func() { a.increment() }() time.Sleep(time.Millisecond) fmt.Println(a.get())}