先看一段代码安全
package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup s := make([]int, 0, 1000) for i := 0; i < 1000; i++ { v := i wg.Add(1) go func() { s = append(s, v) wg.Done() }() } wg.Wait() fmt.Printf("%v\n", len(s)) }
结果架构
第一次:928 第二次:945 第三次:986 ……
多运行几回你就会发现,slice长度并非1000,而是不停的在变,为何呢?(若是这个代码你没法重现,你能够尝试将1000改成更大的数字)并发
由于append并非并发安全的。app
咱们举一个简单例子,好比,当A和B两个协程运行append的时候同时发现s[1]这个位置是空的,他们就都会把本身的值放在这个位置,这样他们两个的值就会覆盖,形成数据丢失。code
那该怎么写?最简单的方式就是用锁,贴一个例子协程
package main import ( "fmt" "sync" ) func main() { var ( wg sync.WaitGroup mutex sync.Mutex ) s := make([]int, 0, 1000) for i := 0; i < 1000; i++ { v := i wg.Add(1) go func() { mutex.Lock() s = append(s, v) mutex.Unlock() wg.Done() }() } wg.Wait() fmt.Printf("%v\n", len(s)) }
运行一下这个例子就会发现,s的长度老是1000。it
更多架构、PHP、GO相关踩坑实践技巧请关注个人公众号:PHP架构师import