Golang happen before

Go语言的happen-before原则确保了并发执行的安全性。它规定了如goroutine创建、channel操作、mutex和sync.WaitGroup等同步原语的行为。例如,channel的发送发生在接收完成之前,mutex解锁发生在下一次锁定之前。理解这些规则对于编写并发程序至关重要,避免数据竞争和不确定行为。
摘要由CSDN通过智能技术生成

Happen before定义

In the following descriptions, if we say event A is guaranteed to happen before event B, it means any of the goroutines involved in the two events will observe that any of the statements presented before event A in source code will be executed before any of the statements presented after event B in source code. For other irrelevant goroutines, the observed orders may be different from the just described.

首先happen before语义针对的是相关的协程,非相关协程观察到的顺序可以是不一样的;

其次,如果A语句happen before B语句,那么B语句之后一定能观察到所有A语句之前的语句;

不相关协程的例子

func f4() {
	var a, b, x, y int
	c := make(chan bool)

	go func() {
		a = 1
		c <- true
		x = 1
	}()

	go func() {
		b = 1
		<-c
		y = 1
	}()

	// Many data races are in this goroutine.
	// Don't write code as such.
	go func() {
		if x == 1 {
			if a != 1 { // possible
				panic("a != 1") // may happen
			}
			if b != 1 { // possible
				panic("b != 1") // may happen
			}
		}

		if y == 1 {
			if a != 1 { // possible
				panic("a != 1") // may happen
			}
			if b != 1 { // possible
				panic("b != 1") // may happen
			}
		}
	}()
}

Here, for the third goroutine, which is irrelevant to the operations on channel c. It will not be guaranteed to observe the orders observed by the first two new created goroutines. So, any of the four panic calls may get executed.

第三个协程没有channel(这里的channel是一个happen before语音,后文中所有提到的happen before语义均在这儿适用),所以它观察到的变量赋值顺序可能和有happen before语义中的协程中不同。

相关语法

goroutine创建

The creation of a goroutine happens before the execution of the goroutine

创建协程语句happen before被创建协程的执行

channel

1 The nth successful send to a channel happens before the nth successful receive from that channel completes, no matter that channel is buffered or unbuffered.(无论channel是否有capacity,对同一个数据的操作,将该数据push进channel happen before从该channel中读取到该数据)

2 The nth successful receive from a channel with capacity m happens before the (n+m)th successful send to that channel completes. In particular, if that channel is unbuffered (m == 0), the nth successful receive from that channel happens before the nth successful send on that channel completes.(如果一个channel的capacity为m,那么第n次接受到channel中的数据happen before第m+n次向channel中push数据。特例情况,若该channel的capacity=0,那么接受到数据的操作happen before向channel中push同一数据的操作。与之前的定义相结合,对于不带buffer的channel,push和pull操作互为happen before,它们被认为是一对同步事件。另一种解释是 开始发送 happen before 接受完成,开始接受 happen before 发送完成)

3 The closing of a channel happens before a receive completes if the receive returns a zero value because the channel is closed.(对于channel的关闭happen before接收到该关闭消息)

mutex

1 For an addressable value m of type Mutex or RWMutex in the sync standard package, the nth successful m.Unlock() method call happens before the (n+1)th m.Lock() method call returns.(第n次的unlock操作 happen before第n+1次lock操作)

2 For an addressable value rw of type RWMutex, if its nth rw.Lock() method call has returned, then its successful nth rw.Unlock() method call happens before the return of any rw.RLock() method call which is guaranteed to happen after the nth rw.Lock() method call returns.(对于读写锁,一旦写锁操作成功,那么它对应的unlock操作happen before所有随后的读锁)

3 For an addressable value rw of type RWMutex, if its nth rw.RLock() method call has returned, then its mth successful rw.RUnlock() method call, where m <= n, happens before the return of any rw.Lock() method call which is guaranteed to happen after the nth rw.RLock() method call returns.(对于读写锁,当第n次的读锁加锁成功,那么所有之前加锁成功的读锁对应的解锁操作,happen before随后的写锁加锁成功)

sync.WaitGroup

At a given time, assume the counter maintained by an addressable sync.WaitGroup value wg is not zero. If there is a group of wg.Add(n) method calls invoked after the given time, and we can make sure that only the last returned call among the group of calls will modify the counter maintained by wg to zero, then each of the group of calls is guaranteed to happen before the return of a wg.Wait method call which is invoked after the given time.

所有的wg.Add操作都happen before wg.Wait语句返回

sync.Once

Among these o.Do method calls, only exact one argument function will be invoked. The invoked argument function is guaranteed to exit before any o.Do method call returns. In other words, the code in the invoked argument function is guaranteed to be executed before any o.Do method call returns.

被实际调用的o.Do函数一定happen before所有调用o.Do函数返回之前

程序初始化

程序的初始化是发生在一个goroutine内的,这个goroutine可以创建多个新的goroutine,创建的goroutine和当前的goroutine可以并发的运行。

如果在一个goroutine所在的源码包p里面通过import命令导入了包q,那么q包里面go文件的初始化方法的执行会happens before 于包p里面的初始化方法执行。

Main package的init函数happen before main函数的执行

参考资料

Memory Order Guarantees in Go - Go 101: an online Go programming book + knowledge base

GoLang内存模型 - 云+社区 - 腾讯云

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值