微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Golang:避免竞争条件

在Go中防止种族状况有哪些好的做法?

我能想到的唯一一个就是不在goroutine之间共享数据 – 父goroutine发送一个对象的深层副本而不是对象本身,所以child goroutine不能改变父对象的内容.这将消耗更多的堆内存,但另一种方法是学习Haskell:P

编辑:同样,是否有任何情况我上面描述的方法仍然可以遇到竞争条件?

即使使用非共享数据结构,竞争条件肯定仍然存在.考虑以下:
B asks A for the currentCount
C asks A for the currentCount
B sends A (newDataB,currentCount + 1)
A stores newDataB at location currentCount+1
C sends A (newDataC,currentCount + 1)
A stores newDataC at currentCount + 1 (overwriting newDataB; race condition)

这种竞争条件要求A中的私有可变状态,但是没有可变的共享数据结构,甚至不需要B或C中的可变状态.如果不理解A提供的合同,B或C就无法阻止这种竞争条件.

一旦状态进入等式,即使是哈斯克尔也会遇到这种竞争条件,并且状态很难完全从实际系统中消除.最终你希望你的程序与现实互动,现实是有状态的.维基百科使用STM提供a helpful race condition example in Haskell.

我同意良好的不可变数据结构可以使事情变得更容易(Go并不真正拥有它们).可变副本将一个问题换成另一个问题.您不能无意中更改其他人的数据.另一方面,当您实际上只是更改副本时,您可能会认为您正在更改真实的副本,从而导致出现其他类型的错误.你必须以任何方式理解合同.

但最终,Go倾向于遵循C的并发历史:你为你的代码制定一些所有权规则(比如@ tux21b商品)并确保你总是遵循它们,如果你完美地完成它,那么一切都会很好,如果你犯了错误,那么显然这是你的错,而不是语言.

(不要误解我的意思;我非常喜欢Go.它提供了一些很好的工具来简化并发.它只是没有提供很多语言工具来帮助使并发性正确.这取决于你.这就是说.,tux21b的答案提供了很多好的建议,而竞赛探测器绝对是减少竞争条件的有力工具.它不是语言的一部分,而是关于测试,而不是正确性;它们不是一回事.)

编辑:关于为什么不可变数据结构使事情变得容易的问题,这是你的初始点的扩展:创建一个多方不改变相同数据结构的契约.如果数据结构是不可变的,那么这是免费的……

许多语言都有丰富的不可变集合和类. C让你几乎可以做任何事情. Objective-C具有可变子类的不可变集合(它创建一组不同于const的模式). Scala具有许多集合类型的单独的可变和不可变版本,并且通常的做法是仅使用不可变版本.在方法签名中声明不变性是合同的重要标志.

当你将[]字节传递给goroutine时,无法从代码中知道goroutine是否打算修改切片,也不能自己修改切片.有一种模式出现了,但它们在移动语义之前就像C对象所有权;很多很好的方法,但无法知道哪一个正在使用.每个程序都需要正确执行它是一件至关重要的事情,但是语言没有为您提供好的工具,开发人员也没有使用通用模式.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1、Golang指针 在介绍Golang指针隐式间接引用前,先简单说下Go 语言的指针 (Pointer),一个指针可以指向任何一个值的内存地址 它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关。大致上理解如下: 变量名前的
1、概述 1.1 Protocol buffers定义 Protocol buffers 是语言中立、平台中立、可扩展的结构化数据序列化机制,就像 XML,但是它更小、更快、更简单。你只需定义一次数据的结构化方式,然后就可以使用特殊生成的源代码轻松地将结构化数据写入和读取各种数据流,支持各
判断文件是否存在,需要用到"os"包中的两个函数: os.Stat()和os.IsNotExit() func Stat(name string) (FileInfo, error) Stat返回描述文件f的FileInfo类型值。如果出错,错误底层类型是*PathError。 func IsNot
1、编译环境 OS :Loongnix-Server Linux release 8.3 CPU指令集 : loongarch64 平台 : 龙芯 go版本 : go version go1.15.6 linux/loong64 2、go和docker安装 docker安装: y
1、概述 Golang是一种强类型语言,虽然在代码中经常看到i:=12这种写法,这其实是编译器在编译期间自动做了类型推断。编译器会对数据进行类型检查,不同类型的数据不能赋值,不能在函数中传参。强类型语言有一些优势,很多的错误会在编译期间被检查出来,不像php和python等弱类型语言,很多错误只有运
1、概述 在《Golang常用语法糖》这篇博文中我们讲解Golang中常用的12种语法糖,在本文我们主要讲解下接收者方法语法糖。 在介绍Golang接收者方法语法糖前,先简单说下Go 语言的指针 (Pointer),大致上理解如下: 变量名前的 & 符号,是取变量的内存地址,不是取
1、概述 1.1 什么是gRPC RPC的全称是Remote Procedure Call,远程过程调用。RPC是一种协议,它实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。 而gRP
1、概述 在Golang语言中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。 2、Go语言函数变量详解 定义 func fun() { } var f func() f = fun 说明 我们首先定义了一个 fun 的函数,接着我们声明了一个
1、概述 Swagger是全球最大的OpenAPI规范(OAS)API开发工具框架,支持从设计和文档到测试和部署的整个API生命周期的开发。Swagger是目前最受欢迎的RESTful Api文档生成工具之一,主要的原因如下: 跨平台、跨语言的支持 强大的社区 生态圈 Swagger Tools(S
1、 概述 Protocol buffers 是语言中立、平台中立、可扩展的结构化数据序列化机制,就像 XML,但是它更小、更快、更简单。你只需定义一次数据的结构化方式,然后就可以使用特殊生成的源代码轻松地将结构化数据写入和读取各种数据流,支持各种语言。因为profobuf是二进制数据格式,需要编码