文档章节

golang append的并发问题

anoty
 anoty
发布于 2017/02/15 21:57
字数 343
阅读 207
收藏 0

先看一段代码

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并不是并发安全的。

我们举一个简单例子,比如,当A和B两个协程运行append的时候同时发现s[1]这个位置是空的,他们就都会把自己的值放在这个位置,这样他们两个的值就会覆盖,造成数据丢失。

那该怎么写?最简单的方式就是用锁,贴一个例子

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。

更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师

© 著作权归作者所有

共有 人打赏支持
anoty
粉丝 25
博文 42
码字总数 26186
作品 0
浦东
私信 提问
加载中

评论(2)

anoty
anoty

引用来自“hlj2722”的评论

第一个例子,我运行了好多次也并无你说的问题呢,我的GO 版本 1.7.4
那就把1000改为改大一点试试
h
hlj2722
第一个例子,我运行了好多次也并无你说的问题呢,我的GO 版本 1.7.4
基于 PHP 协程的网络服务框架--Zan PHP Framework

Zan PHP Framework 是有赞开源的基于 PHP 协程的网络服务框架,提供最简单的方式开发面向 C10K+ 的高并发SOA服务和RPC服务。 该项目每天为2,000+个服务提供300,000,000+次访问量支持,广泛应...

匿名
2017/06/21
2.1K
6
Zan-Group/zanphp

基于 PHP 协程的网络服务框架,提供最简单的方式开发面向 C10K+ 的高并发SOA服务和RPC服务。 每天为2,000+个服务提供300,000,000+次访问量支持,广泛应用于有赞各项业务。 核心特性 基于 实现...

Zan-Group
2017/06/21
0
0
slice for 循环中删除元素

slice for 循环中删除元素 方法1 Golang Delete Slice Item in Range Problem 方法二 Find and delete elements from slice in golang 不改原slice 参考...

solate
01/07
0
0
goroutine, channel 和 CSP

引子 老听 clojure 社区的人提起 core.async ,说它如何好用,如何简化了并发编程的模型,不由得勾起了我的好奇心,想了解一番其思想的源头:CSP 模型及受其启发的 goroutine 和 channel 。 ...

wangxuwei
2018/01/29
0
0
Mecached Client for Golang

Memcached Client for Golang golang版本的memcached客户端,使用二进制协议,支持分布式,支持连接池,支持多种数据格式 特性 支持多server集群 与memcached使用二进制协议通信 支持连接池 ...

盘古大叔
2016/02/26
382
0

没有更多内容

加载失败,请刷新页面

加载更多

eggjs与sequelize简单demo

参考 egg 官方文档 安装 // 依赖npm install --save egg-sequelize mysql2// ts 类型npm install --save @types/sequelize 插件,config/plugin.ts import { EggPlugin } from 'egg';......

Geeyu
53分钟前
1
0
看过上百部片子的这个人教你视频标签算法解析

本文由云+社区发表 随着内容时代的来临,多媒体信息,特别是视频信息的分析和理解需求,如图像分类、图像打标签、视频处理等等,变得越发迫切。目前图像分类已经发展了多年,在一定条件下已经...

腾讯云加社区
今天
4
0
2. 红黑树

定义:红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树(Binary Search Tree)。 要理解红黑树,先要了解什么是二叉查找树。在上一章中,我们学习了什么是二叉树,以及二叉树...

火拳-艾斯
今天
3
0
input的button类型,点击页面跳转

一、input type=button 不做任何操作 例如: <input type="button" class="btn btn-primary" style="width: 30%" value="返回" onclick="window.location.href='/users/list'"></input> onc......

Sunki
今天
1
0
踩坑:js 小数运算出现精度问题

背景 在学习小程序商城源码时发现了这个问题,单价可能出现小数,小数之间运算结果会莫名其妙多出一大串数字,比如下面这样👇。 在此之前我是知道 js 中著名的 0.1 + 0.2 != 0.3 的问题的,...

dkvirus
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部