go - 如果并发进程向全局变量写入相同的值会发生什么?
问题描述
我只是想知道是否有可能由于同时将相同的值写入全局变量而导致损坏。我的大脑告诉我这没有什么问题,因为它只是内存中的一个位置,但我认为我应该仔细检查这个假设。
我有并发进程写入全局地图var linksToVisit map[string]bool
。该地图实际上是在跟踪网站上的哪些链接需要进一步爬取。
但是,并发进程可能在它们各自的页面上具有相同的链接,因此每个进程都会将相同的链接标记为true
并发。在这种情况下不使用锁没有任何问题,对吧?注意:我从不将值更改回,false
因此键存在且其值为 true 或不存在。
IE
var linksToVisit = map[string]bool{}
...
// somewhere later a goroutine finds a link and marks it as true
// it is never marked as false anywhere
linksToVisit[someLink] = true
解决方案
如果并发进程向全局变量写入相同的值会发生什么?
数据竞争的结果是不确定的。
运行 Go 数据竞争检测器。
参考:
在 Go 1.6 中,运行时添加了轻量级、尽力而为的并发滥用地图检测。此版本改进了该检测器,支持检测同时写入和迭代映射的程序。
与往常一样,如果一个 goroutine 正在写入 map,则其他 goroutine 不应该同时读取(包括迭代)或写入 map。如果运行时检测到这种情况,它会打印诊断信息并使程序崩溃。找出更多问题的最佳方法是在比赛检测器下运行程序,这将更可靠地识别比赛并提供更多细节。
例如,
package main
import "time"
var linksToVisit = map[string]bool{}
func main() {
someLink := "someLink"
go func() {
for {
linksToVisit[someLink] = true
}
}()
go func() {
for {
linksToVisit[someLink] = true
}
}()
time.Sleep(100 * time.Millisecond)
}
输出:
$ go run racer.go
fatal error: concurrent map writes
$
$ go run -race racer.go
==================
WARNING: DATA RACE
Write at 0x00c000078060 by goroutine 6:
runtime.mapassign_faststr()
/home/peter/go/src/runtime/map_faststr.go:190 +0x0
main.main.func2()
/home/peter/gopath/src/racer.go:16 +0x6a
Previous write at 0x00c000078060 by goroutine 5:
runtime.mapassign_faststr()
/home/peter/go/src/runtime/map_faststr.go:190 +0x0
main.main.func1()
/home/peter/gopath/src/racer.go:11 +0x6a
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:14 +0x88
Goroutine 5 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:9 +0x5b
==================
fatal error: concurrent map writes
$
推荐阅读
- php - 在浏览器中连接oracle
- django - 从 django 中的页面添加 Facebook 登录和数据收集(社交身份验证)
- php - 在 Woocommerce 中显示或隐藏所选运输方式更改的 html 元素
- php - 如何使用 PHP 在我的服务器链接上保存文件?
- actionscript-3 - 如何在 as3 中平滑图像的“缩放”和“平移”
- excel - VBA - 在行中搜索字符串,然后将其复制并粘贴到不同的列
- windows - 如何使用 PowerShell 远程执行 VBScript?
- c++ - 将共享指针传递给函数参数-将其分配给局部变量的正确方法是什么
- javascript - Vuejs 使用 v-for 添加和删除类
- javascript - 使用字符串页面名称而不是组件时未捕获的承诺无效链接