闭包,sync使用细节

代码

先看代码如下:

func main() {var a []intfor i := 0; i < 100; i++ {go func() {a = append(a, i)}()}time.Sleep(2 * time.Second)fmt.Println(a)
}

这段测试代码是想要一个元素为0到100的切片,但是这一小段代码隐藏了很多的问题。

闭包函数

先看这段代码的执行结果:

[10 12 13 13 13 13 21 24 25 28 28 28 28 28 28 29 29 29 36 38 39 39 40 41 41 41 41 41 41 45 45 45 45 46 47 48 49 50 51 52 61 61 61 61 61 61 61 61 61 61 73 73 74 74 75 76 76 77 77 77 77 77 77 77 77 77 83 85 85 88 88 89 91 92 93 93 93 93 93 93 93 93 100 100 100 100 100 100 100]

可以发现有很多元素是相同的,这就是这段代码的第一个错误:使用闭包函数的时候,代码中这种传递参数i的方法并非深copy,而是传递变量指针。解释一下产生这种情况的原因:在并发执行时由于某一个协程修改了i的值,导致多个协程append的时候变量**i**的值发生变化,从而导致有多个重复的元素
将代码修改为:

func main() {var a []intfor i := 0; i < 100; i++ {go func(i int) {a = append(a, i)}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

执行结果为:

[5 4 8 7 2 12 15 13 14 24 22 23 25 18 21 17 20 28 29 31 30 32 33 34 35 36 37 38 39 41 40 42 44 50 45 48 49 55 51 52 53 54 46 47 57 56 58 59 60 65 61 62 63 64 68 66 67 70 69 72 74 71 73 75 76 80 77 78 79 86 81 82 83 85 89 87 88 84 90 91 92 95 93 94 97 96 98 99]

可以看到没有重复元素了,但是却缺少一些元素,这就引出了第二个问题。

多个协程的竞争问题

如上述代码,执行多次都会发现每次执行的结果都会少一些元素,其实真正的原因是没有对于竞争的协程加互斥锁,导致资源的丢失
解释这个问题要对go的数组、切片、以及append机制有一些了解,参考:

Arrays, slices (and strings): The mechanics of 'append'

现在知道我们声明的切片不同于数组,在每次append的时候我们会伴随着内存copy以达到自动扩容目的,在A协程读出a的内存数据时,B协程完成了写入操作,此时A继续append并赋值就会导致,协程B的更新结果丢失。
假如我们将切片换成数组就不存在这个问题:


func main() {var a [100]intfor i := 0; i < 100; i++ {go func(i int) {// a = append(a, i)a[i] = i}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

结果

[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]

或者互斥锁,

func main() {var a []intvar mu sync.Mutexfor i := 0; i < 100; i++ {go func(i int) {mu.Lock()a = append(a, i)mu.Unlock()}(i)}time.Sleep(2 * time.Second)fmt.Println(a)
}

结果

[1 0 2 9 7 8 10 4 5 3 11 6 12 14 13 16 15 23 20 21 22 19 25 24 17 26 18 27 28 29 32 30 31 34 35 36 40 33 37 39 38 42 43 41 44 51 45 49 50 55 52 53 48 54 46 47 57 56 58 59 60 64 61 62 63 68 72 70 71 74 69 75 73 65 66 67 76 79 77 78 85 80 81 82 83 84 86 88 87 90 89 91 92 93 96 94 95 97 98 99]

结论

  • 闭包使用注意变量传递是指针还是值,及注意闭包变量的两种传递方式。
  • 注意线程安全。

结语

希望大家一起学习,一起交流,一起进步!

联系我
qq:820932773
gmail: jdqaffairs@gmail.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dynamic 仪表板_仪表板完成百万美元交易

dynamic 仪表板问题 (The Problem) Anybody dealing with tech products and data-focused services runs into the same fundamental problem: what you do is technical but non-technical people control the budget. In other words:任何处理高科技产品和以数据为中心的服务…

checkStyle -- 代码风格一致

download page: http://sourceforge.net/project/showfiles.php?group_id80344&package_id107587 转载于:https://www.cnblogs.com/xuqiang/archive/2010/10/26/1953431.html

在线VS Code阅读源码神器 github1s

大家好&#xff0c;我是若川。github1s大部分人知道了&#xff0c;但还是有一部分不知道。我在掘金发过沸点和知乎发过想法还是有挺多人不知道&#xff0c;所以再发公众号推荐下。点击下方卡片关注我、加个星标。学习源码整体架构系列、年度总结、JS基础系列近日&#xff0c;一…

lenze变频器怎么更改地址_英威腾变频器GD300维修

英威腾变频器GD300维修英威腾变频器GD300维修41. 问题&#xff1a;变频器跟PLC采用485通讯不上答&#xff1a;1.检查变频器的通讯地址是否正确&#xff0c;如果采用通讯启动&#xff0c;检查P0.01是否为1&#xff0c;如果通过通讯设定频率&#xff0c;检查P0.068&#xff0c;P0…

代码设计的基础原则_设计原则:良好设计的基础

代码设计的基础原则As designers, it’s our goal to pass information in the most pleasing way possible. Starting out, there’s a wealth of literature to read and videos to watch that can get quite overwhelming to take in at a glance. People take different ro…

java金额类型_Java中存储金额用什么数据类型?

很早之前, 记得一次面试, 面试官问存储金钱用什么数据类型? 当时只知道8种数据类型(boolean, byte, short, int, long, float, double, char)的我, 回答了double, 因为我觉得double是双精度类型, 最适合, 但是面试官告诉我应该用BigDecimal! 最近在做支付的项目, 才对这种数据…

React Hooks 不知道怎么学?看这篇

大家好&#xff0c;我是若川。最近跟朋友聊技术&#xff0c;发现越来越多的大厂&#xff0c;都优先考虑用 React 做项目&#xff0c;在面试中也经常会考察对 React Hooks 的理解。其实&#xff0c;我一直觉得&#xff0c;React 才是前端的正确打开方式。当然&#xff0c;并不是…

ui原型设计工具_UI设计师的工具包,用于专业模型,原型和产品插图

ui原型设计工具This is a followup to my previous article 这是我上一篇文章的后续 visual tools for UX Designers视觉工具Tools don’t make designs better– you do! It doesn’t matter if you paid a lot of money for the latest software, or if you simply have a p…

前端 Offer 提速:如何写出有亮点的简历

大家好&#xff0c;我是若川。今天推荐一篇8年工作经验字节大佬的文章&#xff0c;如何写出有亮点的简历。可以收藏常看。点击下方卡片关注我、加个星标。学习源码整体架构系列、年度总结、JS基础系列先来个灵魂拷问&#xff1a;「你与他人相比&#xff0c;有什么能形成明显区分…

2008中的membership profile操作(转)

<profile > <properties> <add name"jimmy" /> </< span>properties> </< span>profile> 然后就那么简单,后台就能通过Profile拿到: Profile.jimmy "Pumpkin Ravioli"; 然后~通过这种方式就跟Session一样&a…

css网格_一个CSS网格可以全部统治

css网格The case for using one CSS grid for your entire website在整个网站上使用一个CSS网格的情况 CSS网格与Flexbox (CSS Grid vs Flexbox) In the dark ages, we used table, a few years ago we used float and before today most of us used flex . Of course, these …

java 高级泛型_Java 泛型高级

1、限制泛型可用类型在定义泛型类别时&#xff0c;预设可以使用任何的类型来实例化泛型中的类型&#xff0c;但是如果想要限制使用泛型的类别时&#xff0c;只能用某个特定类型或者其子类型才能实例化该类型时&#xff0c;使用extends关键字指定这个类型必须是继承某个类&#…

2021 年最值得使用的 Node.js 框架

大家好&#xff0c;我是若川。今天推荐一篇译文&#xff1a;2021年最值得使用nodejs框架&#xff0c;值得收藏&#xff0c;很快能看完。点击下方卡片关注我、加个星标。学习源码整体架构系列、年度总结、JS基础系列Node.js 是最敏捷的服务端 web 应用平台&#xff0c;因为它为应…

面试被拒绝如何争取_争取反馈

面试被拒绝如何争取Let me start by saying that Dribbble is awesome. I’ve been a member of the Dribbble community for years. I swoon over the beautiful design I see throughout the site. Dribbble is among the most popular places to go for inspiration and whi…

中台之上(二):为什么业务架构存在20多年,技术人员还觉得它有点虚?

业务架构这个词大家时常听到&#xff0c;但是能解释得清楚的却不多&#xff0c;撩撩度娘&#xff0c;你就会发现&#xff0c;不少人问及业务架构和应用架构的关系&#xff0c;聊天时&#xff0c;也常有人问起业务架构师和产品经理什么区别&#xff1f;业务架构分析和需求分析什…

你对webpack了解多少?

大家好&#xff0c;我是若川。之前有一个朋友给我留言&#xff1a;自己目前在一家小厂工作&#xff0c;对webpack的使用比较熟悉&#xff0c;想要跳槽去大厂&#xff0c;但是纠结是否还需要深入学习webpack&#xff08;因为觉得学了也用不到&#xff0c;但又怕面试不通过&#…

纹理对象纹理单元纹理目标_网页设计理论:纹理

纹理对象纹理单元纹理目标Texture has become an indispensable element in web design. It is not only a trend but also a quick way to increase the depth of web pages. When designers learn to use textures, they can strengthen the appeal of web pages. It can be …

java dao层和base层_详解Javaee Dao层的抽取

有时候我们在实现不同功能的时候回看到很多的Dao层的增加、修改、删除、查找都很相似&#xff0c;修改我们将他们提取BaseDao一、提取前1. 提取前的LinkDao层&#xff1a;public interface LinkManDao {Integer findCount(DetachedCriteria detachedCriteria);List findByPage(…

畅销书《深入浅出Vue.js》作者,在阿里淘系1年的收获成长

大家好&#xff0c;我是若川。今天推荐一篇95年的博文的文章。他的故事应该挺多人知道。如果不知道可以看他的博客 https://github.com/berwin/blog点击下方卡片关注我、加个星标时间好快&#xff0c;眨眼间&#xff0c;加入阿里已经一年了。这一年发生了很多事&#xff0c;整体…

插图 引用 同一行两个插图_将图标变成插图的五个简单步骤

插图 引用 同一行两个插图Every creative person has probably already been in this situation: A project, be it a website, an app — or as far as I am concerned: often a news story would benefit from an appealing side visual. But neither budget nor time makes …