【Go】内存模型中的内存可见性

news2024/11/28 23:36:59

前言

使用go必然会使用到协程以及其他的并发操作,初期学习的时候,经常在启动协程时操作变量出现问题,要么就是变量没更新,要么就是各种崩溃,或者vscode报告警之类的,于是浅看了一下Go的内存模型,也了解到Happens Before的概念,这里记录一下;

原文链接:go内存模型,可能要挂梯子

正文

原文开篇的建议部分很有意思:

If you must read the rest of this document to understand the behavior of your program, you are being too clever.
Don’t be clever.

其实是建议大家好好看看内存模型的详述内容,不要自作聪明;

内存模型描述了程序执行的需求,这里的程序执行指的是由goroutine执行创建的(goroutine executions);一个内存操作由4种信息定义:

  • 操作的类型,表明它是一个普通的数据读取,普通的数据写入,还是一个同步操作,如原子数据访问,互斥操作,或通道操作;
  • 在代码中的位置;
  • 被访问的内存位置或变量;
  • 操作读取或写入的值;

goroutine executions为由单个goroutine执行的一组内存操作,我的理解就是一个协程中发生的内存操作;

关键概念

为了便于更好的理解后面的内容,我们需要理解几种关系术语:

happens-before(先于发生):

当线程1中的操作A先执行,而线程2中的操作B后执行时,A就happens-beforeB。happens-before是用来表示两个线程中两个操作被执行的先后顺序的一种描述。

happens-bofore有三个特点:

可传递性。如果Ahappens-beforeB,Bhappens-beforeC,则有Ahappens-beforeC;
当store操作A与load操作B发生同步时,则Ahappens-beforeB;
happens-before一般用于描述分别位于两个线程中的操作之间的顺序。

sequenced-before

如果在单个线程内操作A发生在操作B之前,则表示为Asequenced-beforeB。这个关系是描述单个线程内两个操作之前的先后执行顺序的,与happens-before是相对的。

此外,sequenced-before也具有可传递性,并且sequenced-beforehappences-before之间也具有可传递性:如果线程1中操作Asequenced-before操作B,而操作Bhappences-before线程2中的操作C,操作Csequenced-before线程2中的操作D,则有操作Ahappences-before操作D。

参考文章:
聊聊内存模型和内存序
C++11内存模型完全解读-从硬件层面和内存模型规则层面双重解读

数据竞争

首先,对数据竞争进行定义,数据竞争对内存位置的写入与对同一位置的另一个读或写同时发生,除非所涉及的所有访问都是由sync/atomic包提供的操作,理解来说就是操作是否是数据安全的。

以下模拟了一个发生数据竞争的场景:

func main() {
	var a int
	go func() {
		a = 2
		fmt.Println("goroutine: ", a)
	}()

	go func() {
		a = 3
		fmt.Println("goroutine: ", a)
	}()
	a = 10
	time.Sleep(1 * time.Second)
}

启动2个协程,同时修改a的值,测试运行,加上-race参数,将会打印数据竞争的发生情况:
在这里插入图片描述

Happens Before

Happens Before也叫先行发生,这也是Go中的读写操作要求,先行发生是在 Go 程序的内存操作中局部的执行顺序,既然有Happens Before那么就有Happens After,假设有两个事件e1和e2,有以下概念:

  • e1发生于e2之前:e1 Happens Before 于 e2
  • e1发生于e2之后:e1 Happens After 于 e2
  • e1既不发生于e2之前,也不发生于之后:e1,e2同时发生

几个特征

特征一

对于每个协程内的内存操作,从内存中读取值或者向内存中写入值,都应该是符合正确的顺序执行;也就是运行流程符合sequenced before关系,因为在单个协程内,不存在并发;

一个Go程序运行会被抽象为一组goroutine执行,并伴随一个Map W;W中会指定每个读类型操作的来源写操作

特征二

如果一个同步的读类内存操作r观察到一个同步的写类内存操作w,那么w synchronized before r

特征三

对于一个普通操作(非同步的)数据R,内存地址为X,满足以下条件时对R的写操作w对读操作r可见:

  • w happens before r;
  • 不存在其他的写操作w1 happens after w,且happens before r,即这样的结构:w happens before w1 happens before r;

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

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

相关文章

离散制造业ERP系统对生产物料管理有哪些帮助?

在离散制造企业生产加工过程中,生产物料管理是一个至关重要的环节。车间物料能不能管控好,影响着整个产品的品质、工作效率及制造成本的控制等。离散制造业通常需要品类、属性繁多的原材料和配套件,而各类物料的及时供应十分重要;…

优思学院|QCC 是什么意思?有什么用?

QCC 的中文意思是质量控制圈,也有人称为品质圈。 质量控制圈(QCC)是来自日本的一种质量管理方法,这个概念的作者是石川馨、日本科学家和工程师联盟(JUSE)共同发明。 QCC的方法是建立由5-11名成员组成的小团…

【VUE2-01】vue2的起步

文章目录一、初识vue1.1vue.js的特点1.2什么是虚拟的dom?1.3为什么使用虚拟的dom1.4vue设计思想二、第一个vue应用如果想系统细致的学习,建议阅读vue的官方网站目前vue官网默认的是vue3的内容,此篇以vue2为基础开始学习一、初识vue 1.1vue.j…

电脑重装系统后没声解决步骤

电脑重装系统之后,发现声音功能,不能正常使用了。对于电脑小白来说,不知道该如何处理,下面就和大家说说重装系统后没声音怎么办呢?,其实完全可以自己处理这种情况,快来看看小白重装系统后没声解决方法吧! …

插入损耗——线对上的信号衰减

“您好,我需要您的帮助。我在测试长距离线缆的时候,插入损耗没有通过测试!”这是在对铜缆布线进行验收测量时,我们经常能够听到的问题。针对这一情况,为了能提供更专业的支持,我们必须了解这一电气特性的基…

如何修改linux下的vim复制行数限制

vim-如何修改linux下的vim复制行数限制来自北方的小强正在努力成为资深数字IC搬砖工的搬砖工个人根目录下的.vimrc (~/.vimrc)添加如下内容:set viminfo1000,<600linux下&#xff0c;默认最多复制50行&#xff0c;上述修改即将限制改为600行。注意&#xff1a;1 如果.vimrc文…

Arduino固件库的离线安装方式

参考&#xff1a;https://www.cnblogs.com/hilary0614/p/libraries.html https://jingyan.baidu.com/article/9f7e7ec09d90906f281554e1.html&#xff0c;开发板管理器和管理库区别 Arduino 经常推出新的控制器&#xff0c;这些新的控制器可能不在现有的板子型号中&#xff0c;…

【Linux】Linux 项目自动化构建工具 -- make/makefile

&#x1f451;作者主页&#xff1a;进击的安度因 &#x1f3e0;学习社区&#xff1a;进击的安度因&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux 文章目录一、前言二、概念三、demo 实现四、原理与规则1、依赖关系和依赖方法① 感性理解② 深层理解…

回顾 2022

前言回顾过去的 2022 年&#xff0c;感觉自己学习了不少&#xff0c;输出的不多。适合 Golang 新手入门的项目 go-gin-api[1]&#xff0c;今年基本没更新&#xff0c;目前已收到 4.1k star&#xff0c;感谢大家的认可。关于健康今年室外跑步&#xff0c;跑了有 175 km&#xff…

什么蓝牙耳机音质好?发烧友力荐四款好音质蓝牙耳机

随着蓝牙技术的发展&#xff0c;现如今蓝牙耳机的音质越来越可以与有线耳机的音质相媲美了。音质作为选择蓝牙耳机的重要参考因素之一&#xff0c;在我们的日常生活中&#xff0c;不管是听歌、追剧、通话等&#xff0c;音质不一的蓝牙耳机都能带来不一样的听觉体验。下面&#…

提高1--数字三角形模型

1.摘花生 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。 地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。 Hello Kitty只能向东或向南走,不…

Java基础知识复习

文章目录复习1. Java编译和运行2. Java运行环境3. Java注释4. Java中的打印5. 数据类型整形浮点型字符类型字节类型布尔类型数据类型转换强制类型转换隐式类型转换小结6. 变量命名规范7. 运算符算数运算符逻辑运算符移位运算符关系运算符8. switch9. 方法方法的重载可变参数变程…

http请求走私详解

前言 HTTP请求走私是一种干扰网站正常处理从一个或多个用户收到的HTTP请求的方法&#xff0c;请求走私漏洞在本质上通常很关键&#xff0c;允许攻击者绕过安全控制&#xff0c;获得对敏感数据的未授权访问&#xff0c;并直接危害其他应用程序的用户。 随便提一句&#xff1a;…

关系抽取概念及相关论文解读

1.信息抽取概述 信息抽取是构建知识图谱的必要条件。知识图谱中以&#xff08;subject&#xff0c;relation&#xff0c;object&#xff09;三元组的形式表示数据。信息抽取分为两大部分&#xff0c;一部分是命名实体识别&#xff0c;识别出文本中的实体&#xff0c;另外就是关…

【dp】排列问题——零钱兑换和组合总和IV

文章目录零钱兑换组合总和IV零钱兑换 很明显&#xff0c;本题使用完全背包算法&#xff0c;求解的是组合数&#xff0c;直接使用完全背包算法即可&#xff0c;为什么是组合数呢&#xff1f; 如果题目说 amount5&#xff0c;coins[1,2,5] 有9种方法&#xff0c;那就是排列数&am…

探秘SSD磨损均衡和闪存管理

一块2TB的SSD要进行3000PE耐久度测试&#xff0c;需要在顺序写入方式下&#xff08;写入放大比接近1&#xff09;写入2TB x 30006000TB的数据&#xff0c;这需要相当长的时间才能完成。有朋友可能会问&#xff1a;在SSD里划分一个1GB容量的小分区&#xff0c;往里面覆盖写入300…

2022年总结:责任驱动开源

文章目录概览阅读2022阅读清单2023 阅读目标文章2022文章列表2023 目标社区WeDataSpherecube-studio &#xff08;aiops平台&#xff09;社区展望小结概览 2022年一年过去&#xff0c;在此总结过往&#xff0c;展望未来&#xff0c;每年都写总结&#xff0c;我希望继往开来&am…

STC单片机基于Keil平台在线调试仿真

STC单片机基于Keil平台在线调试仿真⚡目前STC32G12K128型号的单片机仅支持需要通过SWD接口&#xff08;STC-USB LINK 1D&#xff09;进行调试&#xff0c;STC8H系列可以通过HID接口或者串口进行调试&#xff0c;其他不带HID功能型号的只能通过串口进行调试。 ✨初次调试&#x…

RHCE——编写playbook ansible

1.按照要求定义以下变量。&#xff08;可以在多个位置下定义实现相应操作即可&#xff09; | 变量名 | 值 | | --------- | ------- | | file_name | newfile | | user_name | devops | | pk_name | httpd | 2.编写任务模块在node1和node2主机中根据以上变量值创建对应文本文件…

IPC进程间通信-管道

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、了解进行间通信①进程间通信的必要性②进程间通信的技术背景二、管道①管道原理管道原理&#xff0c;三步走管道pipe②匿名管道进程间通…