zoukankan      html  css  js  c++  java
  • go mem

    一个例子

    思考这段代码输出什么?

    package main
    
    var a, b int
    
    func f() {
    	a = 1
    	b = 2
    }
    
    func g() {
    	println(a)
    	println(b)
    }
    
    func main() {
    	go f()
    	g()
    }
    
    

    实际输出

    0
    0
    

    这段代码的输出其实不固定,简单来讲就是

    软件(编译器)或者硬件(CPU)系统可以根据对代码的分析结果,在一定程度上打乱代码的执行顺序,提高CPU的利用率
    

    Go内存模型两个问题

    • Happens Before
    • 可见性

    To serialize access, protect the data with channel operations or other synchronization primitives such as those in the sync and sync/atomic packages.

    Happens Before

    Within a single goroutine, reads and writes must behave as if they executed in the order specified by the program. That is, compilers and processors may reorder the reads and writes executed within a single goroutine only when the reordering does not change the behavior within that goroutine as defined by the language specification. Because of this reordering, the execution order observed by one goroutine may differ from the order perceived by another. For example, if one goroutine executes a = 1; b = 2;, another might observe the updated value of b before the updated value of a.

    编译器重排

    X = 0
    for i in range(100):
        X = 1
        print X
    

    自动优化

    X = 1
    for i in range(100):
        print X
    

    但是问题是如果我们两个goroutine运行,导致X = 0就会出现问题了,所以通过多个goroutine访问数据,需要序列化访问。

    happens before定义

    To specify the requirements of reads and writes, we define happens before, a partial order on the execution of memory operations in a Go program. If event e1 happens before event e2, then we say that e2 happens after e1. Also, if e1 does not happen before e2 and does not happen after e2, then we say that e1 and e2 happen concurrently.

    机器字

    Reads and writes of values larger than a single machine word behave as multiple machine-word-sized operations in an unspecified order.
    32 位系统和 64 位的系统,cpu 在执行一条指令的时候对于单个机器字长的的数据的写入可以保证是原子的,对于 32 位的就是 4 个字节,对于 64 位的就是 8 个字节,对于在 32 位情况下去写入一个 8 字节的数据时就需要执行两次写入操作,这两次操作之间就没有原子性,那就可能出现先写入后半部分的数据再写入前半部分,或者是写入了一半数据然后写入失败的情况。

    同步

    初始化

    Program initialization runs in a single goroutine, but that goroutine may create other goroutines, which run concurrently.
    If a package p imports package q, the completion of q‘s init functions happens before the start of any of p‘s.
    The start of the function main.main happens after all init functions have finished.

    goroutine的创建

    The go statement that starts a new goroutine happens before the goroutine’s execution begins.

    goroutine的销毁

    The exit of a goroutine is not guaranteed to happen before any event in the progra.

    内存重排

    • C1 执行 a = 1 将 store buffer 中 a 的值写为 1
    • C1 执行 b = 2 将 store buffer 中 b 的值写为 2, 然后由于某种原因将 b 的值写入到了内存中
    • C2 去读取 b 的值,发现缓存中没有,就去内存中读,这时候 print 出来 2
    • C2 去读取 a 的值,发现缓存中没有,就去内存中读,这时候 print 出来 0

    ref

    http://lailin.xyz/post/go-training-week3-go-memory-model.html

  • 相关阅读:
    浏览器内核、webview内核
    移动端(h5)页面适配
    vue 开发多页面应用
    git 指令
    joomla多语言建站之默认前台语言设置
    初识node,原理与浏览器何其相似
    vue-cli下配置项目访问ip和服务器ip
    js中不容小觑的var声明
    vue中的事件监听之——v-on vs .$on
    用js的eval函数模拟Web API中的onclick事件
  • 原文地址:https://www.cnblogs.com/CherryTab/p/14226254.html
Copyright © 2011-2022 走看看