golang append的并发问题

先看一段代码安全

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

相关文章
相关标签/搜索