Golang写时复制是否是原子性的?

Posted 衣舞晨风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang写时复制是否是原子性的?相关的知识,希望对你有一定的参考价值。

建议先阅读下Go汇编语言的入门教程
https://go.dev/doc/asm

先说一下我这边的一个简化场景吧,有一个定时任务定时从数据库获取数据,也就是对应实例代码中的getNewProject(),获取完数据后,会直接赋给变量projectMap(projectMap其实就是作为一个缓存来用的);还会有程序从projectMap获取对应的信息。

这个场景其实就是一个简单的写时复制。对于获取在赋值过程中,获取到旧值,也是允许的。

有个疑问点就是在赋值的这个操作是不是原子的呢?

比如示例代码中的第8行。

验证代码:

package main

var (
        projectMap = make(map[string]*Project)
)

func main() 
        projectMap = getNewProject()


func getNewProject() map[string]*Project 
        items := make(map[string]*Project)

        item := new(Project)
        item.ID = "project_id"
        item.Name = "project_name"

        items[item.ID] = item
        return items



type Project struct 
        ID   string `json:"id"`
        Name string `json:"name"`


在网上也找到一些资料,说是原子性的:

  • 看看开源项目都是如何做的
    • https://github.com/fagongzi/manba/blob/master/pkg/proxy/dispatcher_meta.go#L174
  • 看看一些对于Copy-On-Write的讨论
    • https://chunlife.top/2019/09/03/copy-on-write%E6%8A%80%E6%9C%AF/
    • https://github.com/Terry-Mao/gopush-cluster/issues/44

但终究还是自己探索一下的比较好对吧,哈哈。

要想看这个赋值操作是不是原子性的,那咱们看下汇编代码吧。
查看汇编,咱们分为两步:

  • 编译golang代码为.o文件
  • 反编译.o文件
PS D:\\Code\\Golang\\github\\jiankunking\\cow-test> go tool compile -N -l main\\main.go    
PS D:\\Code\\Golang\\github\\jiankunking\\cow-test> go tool objdump .\\main.o              
TEXT "".main(SB) gofile..D:/Code/Golang/github/jiankunking/cow-test/main/main.go                                                    
  main.go:7             0x22f1                  493b6610                CMPQ 0x10(R14), SP                                          
  main.go:7             0x22f5                  763e                    JBE 0x2335                                                  
  main.go:7             0x22f7                  4883ec08                SUBQ $0x8, SP                                               
  main.go:7             0x22fb                  48892c24                MOVQ BP, 0(SP)                                              
  main.go:7             0x22ff                  488d2c24                LEAQ 0(SP), BP                                              
  main.go:8             0x2303                  e800000000              CALL 0x2308             [1:5]R_CALL:"".getNewProject        
  main.go:8             0x2308                  833d0000000000          CMPL $0x0, 0(IP)        [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:8             0x230f                  6690                    NOPW                                                        
  main.go:8             0x2311                  7402                    JE 0x2315                                                   
  main.go:8             0x2313                  eb09                    JMP 0x231e                                                  
  main.go:8             0x2315                  48890500000000          MOVQ AX, 0(IP)          [3:7]R_PCREL:"".projectMap          
  main.go:8             0x231c                  eb0e                    JMP 0x232c                                                  
  main.go:8             0x231e                  488d3d00000000          LEAQ 0(IP), DI          [3:7]R_PCREL:"".projectMap
  main.go:8             0x2325                  e800000000              CALL 0x232a             [1:5]R_CALL:runtime.gcWriteBarrier<1>
  main.go:8             0x232a                  eb00                    JMP 0x232c
  main.go:9             0x232c                  488b2c24                MOVQ 0(SP), BP
  main.go:9             0x2330                  4883c408                ADDQ $0x8, SP
  main.go:9             0x2334                  c3                      RET
  main.go:7             0x2335                  e800000000              CALL 0x233a             [1:5]R_CALL:runtime.morestack_noctxt
  main.go:7             0x233a                  ebb5                    JMP "".main(SB)

TEXT "".getNewProject(SB) gofile..D:/Code/Golang/github/jiankunking/cow-test/main/main.go
  main.go:11            0x233c                  493b6610                CMPQ 0x10(R14), SP
  main.go:11            0x2340                  0f8600010000            JBE 0x2446
  main.go:11            0x2346                  4883ec58                SUBQ $0x58, SP
  main.go:11            0x234a                  48896c2450              MOVQ BP, 0x50(SP)
  main.go:11            0x234f                  488d6c2450              LEAQ 0x50(SP), BP
  main.go:11            0x2354                  48c744242000000000      MOVQ $0x0, 0x20(SP)
  main.go:12            0x235d                  e800000000              CALL 0x2362                     [1:5]R_CALL:runtime.makemap_small<1>
  main.go:12            0x2362                  4889442428              MOVQ AX, 0x28(SP)
  main.go:14            0x2367                  488d0500000000          LEAQ 0(IP), AX                  [3:7]R_PCREL:type."".Project
  main.go:14            0x236e                  e800000000              CALL 0x2373                     [1:5]R_CALL:runtime.newobject<1>
  main.go:14            0x2373                  4889442430              MOVQ AX, 0x30(SP)
  main.go:15            0x2378                  48c740080a000000        MOVQ $0xa, 0x8(AX)
  main.go:15            0x2380                  833d0000000000          CMPL $0x0, 0(IP)                [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:15            0x2387                  7402                    JE 0x238b
  main.go:15            0x2389                  eb0c                    JMP 0x2397
  main.go:15            0x238b                  488d1500000000          LEAQ 0(IP), DX                  [3:7]R_PCREL:go.string."project_id"
  main.go:15            0x2392                  488910                  MOVQ DX, 0(AX)
  main.go:15            0x2395                  eb11                    JMP 0x23a8
  main.go:15            0x2397                  4889c7                  MOVQ AX, DI
  main.go:15            0x239a                  488d1500000000          LEAQ 0(IP), DX                  [3:7]R_PCREL:go.string."project_id"
  main.go:15            0x23a1                  e800000000              CALL 0x23a6                     [1:5]R_CALL:runtime.gcWriteBarrierDX
  main.go:15            0x23a6                  eb00                    JMP 0x23a8
  main.go:16            0x23a8                  488b542430              MOVQ 0x30(SP), DX
  main.go:16            0x23ad                  8402                    TESTB AL, 0(DX)
  main.go:16            0x23af                  48c742180c000000        MOVQ $0xc, 0x18(DX)
  main.go:16            0x23b7                  488d7a10                LEAQ 0x10(DX), DI
  main.go:16            0x23bb                  833d0000000000          CMPL $0x0, 0(IP)                [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:16            0x23c2                  7402                    JE 0x23c6
  main.go:16            0x23c4                  eb0d                    JMP 0x23d3
  main.go:16            0x23c6                  488d3500000000          LEAQ 0(IP), SI                  [3:7]R_PCREL:go.string."project_name"
  main.go:16            0x23cd                  48897210                MOVQ SI, 0x10(DX)
  main.go:16            0x23d1                  eb10                    JMP 0x23e3
  main.go:16            0x23d3                  488d1500000000          LEAQ 0(IP), DX                  [3:7]R_PCREL:go.string."project_name"
  main.go:16            0x23da                  6690                    NOPW
  main.go:16            0x23dc                  e800000000              CALL 0x23e1                     [1:5]R_CALL:runtime.gcWriteBarrierDX
  main.go:16            0x23e1                  eb00                    JMP 0x23e3
  main.go:18            0x23e3                  488b542430              MOVQ 0x30(SP), DX
  main.go:18            0x23e8                  8402                    TESTB AL, 0(DX)
  main.go:18            0x23ea                  488b0a                  MOVQ 0(DX), CX
  main.go:18            0x23ed                  488b7a08                MOVQ 0x8(DX), DI
  main.go:18            0x23f1                  48894c2440              MOVQ CX, 0x40(SP)
  main.go:18            0x23f6                  48897c2448              MOVQ DI, 0x48(SP)
  main.go:18            0x23fb                  488b5c2428              MOVQ 0x28(SP), BX
  main.go:18            0x2400                  488d0500000000          LEAQ 0(IP), AX                  [3:7]R_PCREL:type.map[string]*"".Project        
  main.go:18            0x2407                  e800000000              CALL 0x240c                     [1:5]R_CALL:runtime.mapassign_faststr<1>
  main.go:18            0x240c                  4889442438              MOVQ AX, 0x38(SP)
  main.go:18            0x2411                  8400                    TESTB AL, 0(AX)
  main.go:18            0x2413                  488b542430              MOVQ 0x30(SP), DX
  main.go:18            0x2418                  833d0000000000          CMPL $0x0, 0(IP)                [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:18            0x241f                  7402                    JE 0x2423
  main.go:18            0x2421                  eb05                    JMP 0x2428
  main.go:18            0x2423                  488910                  MOVQ DX, 0(AX)
  main.go:18            0x2426                  eb0a                    JMP 0x2432
  main.go:18            0x2428                  4889c7                  MOVQ AX, DI
  main.go:18            0x242b                  e800000000              CALL 0x2430                     [1:5]R_CALL:runtime.gcWriteBarrierDX
  main.go:18            0x2430                  eb00                    JMP 0x2432
  main.go:19            0x2432                  488b442428              MOVQ 0x28(SP), AX
  main.go:19            0x2437                  4889442420              MOVQ AX, 0x20(SP)
  main.go:19            0x243c                  488b6c2450              MOVQ 0x50(SP), BP
  main.go:19            0x2441                  4883c458                ADDQ $0x58, SP
  main.go:19            0x2445                  c3                      RET
  main.go:11            0x2446                  e800000000              CALL 0x244b                     [1:5]R_CALL:runtime.morestack_noctxt
  main.go:11            0x244b                  e9ecfeffff              JMP "".getNewProject(SB)

TEXT "".init(SB) gofile..D:/Code/Golang/github/jiankunking/cow-test/main/main.go
  main.go:4             0x2450                  493b6610                CMPQ 0x10(R14), SP
  main.go:4             0x2454                  763e                    JBE 0x2494
  main.go:4             0x2456                  4883ec08                SUBQ $0x8, SP
  main.go:4             0x245a                  48892c24                MOVQ BP, 0(SP)
  main.go:4             0x245e                  488d2c24                LEAQ 0(SP), BP
  main.go:4             0x2462                  e800000000              CALL 0x2467             [1:5]R_CALL:runtime.makemap_small<1>
  main.go:4             0x2467                  833d0000000000          CMPL $0x0, 0(IP)        [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:4             0x246e                  6690                    NOPW
  main.go:4             0x2470                  7402                    JE 0x2474
  main.go:4             0x2472                  eb09                    JMP 0x247d
  main.go:4             0x2474                  48890500000000          MOVQ AX, 0(IP)          [3:7]R_PCREL:"".projectMap
  main.go:4             0x247b                  eb0e                    JMP 0x248b
  main.go:4             0x247d                  488d3d00000000          LEAQ 0(IP), DI          [3:7]R_PCREL:"".projectMap
  main.go:4             0x2484                  e800000000              CALL 0x2489             [1:5]R_CALL:runtime.gcWriteBarrier<1>
  main.go:4             0x2489                  eb00                    JMP 0x248b
  main.go:4             0x248b                  488b2c24                MOVQ 0(SP), BP
  main.go:4             0x248f                  4883c408                ADDQ $0x8, SP
  main.go:4             0x2493                  c3                      RET
  main.go:4             0x2494                  e800000000              CALL 0x2499             [1:5]R_CALL:runtime.morestack_noctxt
  main.go:4             0x2499                  ebb5                    JMP "".init(SB)

TEXT type..eq."".Project(SB) gofile..<autogenerated>
  gofile..<autogenerated>:1     0x2713                  493b6610                CMPQ 0x10(R14), SP
  gofile..<autogenerated>:1     0x2717                  0f8610010000            JBE 0x282d
  gofile..<autogenerated>:1     0x271d                  4883ec58                SUBQ $0x58, SP
  gofile..<autogenerated>:1     0x2721                  48896c2450              MOVQ BP, 0x50(SP)
  gofile..<autogenerated>:1     0x2726                  488d6c2450              LEAQ 0x50(SP), BP
  gofile..<autogenerated>:1     0x272b                  4889442460              MOVQ AX, 0x60(SP)
  gofile..<autogenerated>:1     0x2730                  48895c2468              MOVQ BX, 0x68(SP)
  gofile..<autogenerated>:1     0x2735                  c644241e00              MOVB $0x0, 0x1e(SP)
  gofile..<autogenerated>:1     0x273a                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x273f                  488b5208                MOVQ 0x8(DX), DX
  gofile..<autogenerated>:1     0x2743                  4889542428              MOVQ DX, 0x28(SP)
  gofile..<autogenerated>:1     0x2748                  488b542468              MOVQ 0x68(SP), DX
  gofile..<autogenerated>:1     0x274d                  488b5208                MOVQ 0x8(DX), DX
  gofile..<autogenerated>:1     0x2751                  4889542420              MOVQ DX, 0x20(SP)
  gofile..<autogenerated>:1     0x2756                  4839542428              CMPQ DX, 0x28(SP)
  gofile..<autogenerated>:1     0x275b                  7405                    JE 0x2762
  gofile..<autogenerated>:1     0x275d                  e9b3000000              JMP 0x2815
  gofile..<autogenerated>:1     0x2762                  eb00                    JMP 0x2764
  gofile..<autogenerated>:1     0x2764                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x2769                  488b5218                MOVQ 0x18(DX), DX
  gofile..<autogenerated>:1     0x276d                  4889542420              MOVQ DX, 0x20(SP)
  gofile..<autogenerated>:1     0x2772                  488b542468              MOVQ 0x68(SP), DX
  gofile..<autogenerated>:1     0x2777                  488b5218                MOVQ 0x18(DX), DX
  gofile..<autogenerated>:1     0x277b                  4889542428              MOVQ DX, 0x28(SP)
  gofile..<autogenerated>:1     0x2780                  4839542420              CMPQ DX, 0x20(SP)
  gofile..<autogenerated>:1     0x2785                  7405                    JE 0x278c
  gofile..<autogenerated>:1     0x2787                  e987000000              JMP 0x2813
  gofile..<autogenerated>:1     0x278c                  eb00                    JMP 0x278e
  gofile..<autogenerated>:1     0x278e                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x2793                  488b5208                MOVQ 0x8(DX), DX
  gofile..<autogenerated>:1     0x2797                  4889542428              MOVQ DX, 0x28(SP)
  gofile..<autogenerated>:1     0x279c                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x27a1                  488b12                  MOVQ 0(DX), DX
  gofile..<autogenerated>:1     0x27a4                  4889542448              MOVQ DX, 0x48(SP)
  gofile..<autogenerated>:1     0x27a9                  488b542468              MOVQ 0x68(SP), DX
  gofile..<autogenerated>:1     0x27ae                  488b1a                  MOVQ 0(DX), BX
  gofile..<autogenerated>:1     0x27b1                  48895c2440              MOVQ BX, 0x40(SP)
  gofile..<autogenerated>:1     0x27b6                  488b4c2428              MOVQ 0x28(SP), CX
  gofile..<autogenerated>:1     0x27bb                  488b442448              MOVQ 0x48(SP), AX
  gofile..<autogenerated>:1     0x27c0                  e800000000              CALL 0x27c5                     [1:5]R_CALL:runtime.memequal<1>
  gofile..<autogenerated>:1     0x27c5                  8844241f                MOVB AL, 0x1f(SP)
  gofile..<autogenerated>:1     0x27c9                  84c0                    TESTL AL, AL
  gofile..<autogenerated>:1     0x27cb                  7502                    JNE 0x27cf
  gofile..<autogenerated>:1     0x27cd                  eb41                    JMP 0x2810
  gofile..<autogenerated>:1     0x27cf                  eb00                    JMP 0x27d1
  gofile..<autogenerated>:1     0x27d1                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x27d6                  488b5218                MOVQ 0x18(DX), DX
  gofile..<autogenerated>:1     0x27da                  4889542428              MOVQ DX, 0x28(SP)
  gofile..<autogenerated>:1     0x27df                  488b542460              MOVQ 0x60(SP), DX
  gofile..<autogenerated>:1     0x27e4                  488b5210                MOVQ 0x10(DX), DX
  gofile..<autogenerated>:1     0x27e8                  4889542438              MOVQ DX, 0x38(SP)
  gofile..<autogenerated>:1     0x27ed                  488b542468              MOVQ 0x68(SP), DX
  gofile..<autogenerated>:1     0x27f2                  488b5a10                MOVQ 0x10(DX), BX
  gofile..<autogenerated>:1     0x27f6                  48895c2430              MOVQ BX, 0x30(SP)
  gofile..<autogenerated>:1     0x27fb                  488b4c2428              MOVQ 0x28(SP), CX
  gofile..<autogenerated>:1     0x2800                  488b442438              MOVQ 0x38(SP), AX
  gofile..<autogenerated>:1     0x2805                  e800000000              CALL 0x280a                     [1:5]R_CALL:runtime.memequal<1>
  gofile..<autogenerated>:1     0x280a                  8844241e                MOVB AL, 0x1e(SP)
  gofile..<autogenerated>:1     0x280e                  eb0e                    JMP 0x281e
  gofile..<autogenerated>:1     0x2810                  eb05                    JMP 0x2817
  gofile..<autogenerated>:1     0x2812                  90                      NOPL
  gofile..<autogenerated>:1     0x2813                  eb02                    JMP 0x2817
  gofile..<autogenerated>:1     0x2815                  eb00                    JMP 0x2817
  gofile..<autogenerated>:1     0x2817                  c644241e00              MOVB $0x0, 0x1e(SP)
  gofile..<autogenerated>:1     0x281c                  eb00                    JMP 0x281e
  gofile..<autogenerated>:1     0x281e                  0fb644241e              MOVZX 0x1e(SP), AX
  gofile..<autogenerated>:1     0x2823                  488b6c2450              MOVQ 0x50(SP), BP
  gofile..<autogenerated>:1     0x2828                  4883c458                ADDQ $0x58, SP
  gofile..<autogenerated>:1     0x282c                  c3                      RET
  gofile..<autogenerated>:1     0x282d                  4889442408              MOVQ AX, 0x8(SP)
  gofile..<autogenerated>:1     0x2832                  48895c2410              MOVQ BX, 0x10(SP)
  gofile..<autogenerated>:1     0x2837                  e800000000              CALL 0x283c                     [1:5]R_CALL:runtime.morestack_noctxt    
  gofile..<autogenerated>:1     0x283c                  488b442408              MOVQ 0x8(SP), AX
  gofile..<autogenerated>:1     0x2841                  488b5c2410              MOVQ 0x10(SP), BX
  gofile..<autogenerated>:1     0x2846                  e9c8feffff              JMP type..eq."".Project(SB)
PS D:\\Code\\Golang\\github\\jiankunking\\cow-test> 

先从汇编代码中摘取出,第8行代码对应的汇编

  main.go:8             0x2303                  e800000000              CALL 0x2308             [1:5]R_CALL:"".getNewProject        
  main.go:8             0x2308                  833d0000000000          CMPL $0x0, 0(IP)        [2:6]R_PCREL:runtime.writeBarrier+-1
  main.go:8             0x230f                  6690                    NOPW                                                        
  main.go:8             0x2311                  7402                    JE 0x2315                                                   
  main.go:8             0x2313                  eb09                    JMP 0x231e                                                  
  main.go:8             0x2315                  48890500000000          MOVQ AX, 0(IP)          [3:7]R_PCREL:"".projectMap          
  main.go:8             0x231c                  eb0e                    JMP 0x232c                                                  
  main.go:8             0x231e                  488d3d00000000          LEAQ 0(IP), DI          [3:7]R_PCREL:"".projectMap
  main.go:8             0x2325                  e800000000              CALL 0x232a             [1:5]R_CALL:runtime.gcWriteBarrier<1>
  main.go:8             0x232a                  eb00                    JMP 0x232c

从汇编代码中可以看出,赋值的核心在下面这几句:

// 将AX寄存器中的值赋给0(IP)
  main.go:8             0x2315                  48890500000000          MOVQ AX, 0(IP)          [3:7]R_PCREL:"".projectMap          
// 跳转
  main.go:8             0x231c                  eb0e                    JMP 0x232c                                                  
// 将0(IP)中值的地址赋给DI
  main.go:8             0x231e                  488d3d00000000          LEAQ 0(IP), DI          [3:7]R_PCREL:"".projectMap

从汇编可以看到赋值是只有一步,但获取值及赋值是分开的,也就是说对于写时复制这种场景来说,直接赋值是没有问题的

基础知识补充:

MOVQ

  • movb(8位)、movw(16位)、movl(32位)、movq(64位)

  • 寄存器寻址:

movl %eax, %edx
eax -> edx

https://blog.csdn.net/luoyhang003/article/details/46786591/

TESTB

TEST指令的行为与AND指令一样,除了不改变目的寄存器的值。例如,testq %rax, %rax 用来检查 %rax 是负数、零、还是正数。

LEAQ vs MOVQ

https://stackoverflow.com/questions/1699748/what-is-the-difference-between-mov-and-lea

PCDATA

https://www.cnblogs.com/binHome/p/13034103.html

CMPL

CMPL %eax,%ebx
==> 
[ebx]-[eax],就是把第二个数减去第一个数

JMP

无条件转移指令
JMP 389无条件转至0x0185地址处(十进制389转换成十六进制0x0185)

CALL

调用函数
CALL runtime.printnl(SB)表示通过printnl函数的内存地址发起调用

伪计数器

FP: Frame pointer: arguments and locals.(指向当前栈帧)
PC: Program counter: jumps and branches.(指向指令地址)
SB: Static base pointer: global symbols.(指向全局符号表)
SP: Stack pointer: top of stack.(指向当前栈顶部)
注意: 栈是向下整长 golang的汇编是调用者维护参数返回值跟返回地址。所以FP的值小于参数跟返回值

本机环境

x86-64( 又称x64,即英文词64-bit extended,64位拓展 的简写)是x86架构的64位拓展,向后兼容于16位及32位的x86架构。x64于1999年由AMD设计,AMD首次公开64位集以扩展给x86,称为“AMD64”。

编译命令详解

PS D:\\Code\\Golang\\github\\jiankunking\\cow-test> go tool compile -help
usage: compile [options] file.go...
  -% int
        debug non-static initializers
  -+    compiling runtime
  -B    disable bounds checking
  -C    disable printing of columns in error messages
  -D path
        set relative path for local imports
  -E    debug symbol export
  -G    accept generic code (default 3)
  -I directory
        add directory to import search path
  -K    debug missing line numbers
  -L    show full file names in error messages
  -N    disable optimizations
  -S    print assembly listing
  -V    print version and exit
  -W    debug parse tree after type checking
  -asan
        build code compatible with C/C++ address sanitizer
  -asmhdr file
        write assembly header to file
  -bench file
        append benchmark times to file
  -blockprofile file
        write block profile to file
  -buildid id
        record id as the build id in the export metadata
  -c int
        concurrency during compilation (1 means no concurrency) (default 1)
  -clobberdead
        clobber dead stack slots (for debugging)
  -clobberdeadreg
        clobber dead registers (for debugging)
  -complete
        compiling complete package (no C or assembly)
  -cpuprofile file
        write cpu profile to file
  -d value
        enable debugging settings; try -d help
  -dwarf
        generate DWARF symbols (default true)
  -dwarfbasentries
        use base address selection entries in DWARF (default true)
  -dwarflocationlists
        add location lists to DWARF in optimized mode (default true)
  -dynlink
        support references to Go symbols defined in other shared libraries
  -e    no limit on number of errors reported
  -embedcfg file
        read go:embed configuration from file
  -gendwarfinl int
        generate DWARF inline info records (default 2)
  -goversion string
        required version of the runtime
  -h    halt on error
  -importcfg file
        read import configuration from file
  -importmap definition
        add definition of the form source=actual to import map
  -installsuffix suffix
        set pkg directory suffix
  -j    debug runtime-initialized variables
  -json string
        version,file for JSON compiler/optimizer detail output
  -l    disable inlining
  -lang string
        Go language version source code expects
  -linkobj file
        write linker-specific object to file
  -linkshared
        generate code that will be linked against Go shared libraries
  -live
        debug liveness analysis
  -m    print optimization decisions
  -memprofile file
        write memory profile to file
  -memprofilerate rate
        set runtime.MemProfileRate to rate
  -msan
        build code compatible with C/C++ memory sanitizer
  -mutexprofile file
        write mutex profile to file
  -nolocalimports
        reject local (relative) imports
  -o file
        write output to file
  -p path
        set expected package import path
  -pack
        write to file.a instead of file.o
  -r    debug generated wrappers
  -race
        enable race detector
  -shared
        generate code that can be linked into a shared library
  -smallframes
        reduce the size limit for stack allocated objects
  -spectre list
        enable spectre mitigations in list (all, index, ret)
  -std
        compiling standard library
  -symabis file
        read symbol ABIs from file
  -t    enable tracing for debugging the compiler
  -traceprofile file
        write an execution trace to file
  -trimpath prefix
        remove prefix from recorded source file paths
  -v    increase debug verbosity
  -w    debug type checking
  -wb
        enable write barrier (default true)

拓展阅读

https://stackoverflow.com/questions/70332316/whats-the-differenct-between-go-tool-compile-and-go-tool-objdump

https://xargin.com/plan9-assembly/

https://github.com/cch123/golang-notes/blob/master/assembly.md

https://go.dev/doc/asm

以上是关于Golang写时复制是否是原子性的?的主要内容,如果未能解决你的问题,请参考以下文章

Golang写时复制是否是原子性的?

golang 原子操作函数

创建一个对象和i++是否原子性的理解

写时复制会防止阵列上的数据重复吗?

写时复制会防止阵列上的数据重复吗?

基于记忆性的中值滤波O(r)与O复杂度的算法实现