Go语言

发现问题

今天在看代码的时候,遇见了多个协程写同一个slice的情况,发现未对slice做任何保护,亦未使用其他手段保证并发安全,这样肯定会出错的。

思考

slice不是协程安全的,所以在多个协程中读写slice是不安全的,在高并发的情况下会产生不可控制的错误。

总结

这里记录一下错误的使用方式与正确的使用方式:

错误的使用方式:

1var a []int 2 3for i := 0; i < 10000; i++ { 4 go func() { 5 a = append(a, 1) // 多协程并发读写slice 6 }() 7} 8 9fmt.Println(len(a))

输出结果可能不等于期望的值

正确对方式

第一种方式:

对slice加锁,进行保护

1   num := 10000 2 3 var a []int 4 var l sync.Mutex 5 6 var wg sync.WaitGroup 7 wg.Add(num) 8 9 for i := 0; i < num; i++ { 10 go func() { 11 l.Lock() // 加锁 12 a = append(a, 1) 13 l.Unlock() // 解锁 14 wg.Done() 15 }() 16 } 17 18 wg.Wait() 19 20 fmt.Println(len(a))

缺点:锁会影响性能

第二种方式:

使用channel的传递数据

1num := 10000 2 3 var wg sync.WaitGroup 4 wg.Add(num) 5 6 c := make(chan int) 7 for i := 0; i < num; i++ { 8 go func() { 9 c <- 1 // channl是协程安全的 10 wg.Done() 11 }() 12 } 13 14 // 等待关闭channel 15 go func() { 16 wg.Wait() 17 close(c) 18 }() 19 20 // 读取数据 21 var a []int 22 for i := range c { 23 a = append(a, i) 24 } 25 26 fmt.Println(len(a))

第三种方式:

使用索引

1num := 10000 2 3 a := make([]int, num, num) 4 5 var wg sync.WaitGroup 6 wg.Add(num) 7 8 for i := 0; i < num; i++ { 9 k := i // 必须使用局部变量 10 go func(idx int) { 11 a[idx] = 1 12 wg.Done() 13 }(k) 14 } 15 16 wg.Wait() 17 18 count := 0 19 for i := range a { 20 if a[i] != 0 { 21 count++ 22 } 23 } 24 fmt.Println(count)

优点:无锁,不影响性能

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )