什么是竟態(tài)
當(dāng)多個(gè)routine共享同一資源時(shí)就會(huì)出現(xiàn)竟態(tài)甸祭。比如多個(gè)routine對(duì)同一個(gè)全局變量進(jìn)行+1操作而導(dǎo)致數(shù)據(jù)操作不準(zhǔn)確。
示例:
package main
import (
"fmt"
"sync"
)
func main() {
var count int
var arithmetic sync.WaitGroup
Increment := func() {
count++
}
Decrement := func() {
count--
}
for j := 0; j < 100; j++ {
arithmetic.Add(1)
go func() {
defer arithmetic.Done()
Increment()
}()
}
for i := 0; i < 100; i++ {
arithmetic.Add(1)
go func() {
defer arithmetic.Done()
Decrement()
}()
}
arithmetic.Wait()
fmt.Println("count", count)
}
上面這個(gè)程序缤言,100個(gè)routine并發(fā)執(zhí)行count++欺抗;100個(gè)routine并發(fā)執(zhí)行count--;最后結(jié)果是多少恕沫?
執(zhí)行結(jié)果-竟態(tài)
上述代碼就出現(xiàn)了竟態(tài)监憎,兩個(gè)for循環(huán)一共產(chǎn)生200個(gè)routine并發(fā)操作全局變量count,多個(gè)routine讀取到同一count的值進(jìn)行加減操作婶溯,最后導(dǎo)致count雖然執(zhí)行了100次+1和100次-1鲸阔,但最終結(jié)果卻不為0
sync.Mutex加鎖
我們?cè)賮?lái)看看下面這個(gè)程序
package main
import (
"fmt"
"sync"
)
func main() {
var count int
var lock sync.Mutex
var arithmetic sync.WaitGroup
Increment := func(i int) {
fmt.Println("Inc", i, "waiting the lock")
lock.Lock()
fmt.Println("Inc", i, "lock the lock", count)
defer lock.Unlock()
count++
fmt.Println("Inc", i, "unlock the lock", count)
fmt.Println()
}
Decrement := func(i int) {
fmt.Println("Dec", i, "waiting the lock")
lock.Lock()
fmt.Println("Dec", i, "lock the lock", count)
defer lock.Unlock()
count--
fmt.Println("Dec", i, "unlock the lock", count)
fmt.Println()
}
for j := 0; j < 100; j++ {
arithmetic.Add(1)
go func(i int) {
defer arithmetic.Done()
Increment(i)
}(j)
}
for i := 0; i < 100; i++ {
arithmetic.Add(1)
go func(i int) {
defer arithmetic.Done()
Decrement(i)
}(i)
}
arithmetic.Wait()
fmt.Println("count", count)
}
執(zhí)行結(jié)果-截取一部分
通過(guò)sync.Mutex加鎖的方式阻塞routine搶奪同一資源偷霉,雖然解決了竟態(tài)的問(wèn)題,但也失去了routine的作用,代碼相當(dāng)于是在順序執(zhí)行。
結(jié)語(yǔ)
我們?cè)谟胷outine的時(shí)候一定要避免竟態(tài)的出現(xiàn)初嘹,另外網(wǎng)上有很多檢測(cè)竟態(tài)的方法可以用起來(lái)孝凌。