「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」。
上篇文章讲了sellock,接下来接着继续看
selunlock
1 | go复制代码func selunlock(scases []scase, lockorder []uint16) { |
首先第一个看到的问题就是相对于sellock,他的遍历顺序恰恰相反,这里猜测是像for循环的大括号一样(不恰当的比喻,不过之前操作系统的加锁解锁方式也遵循这种规律)
照例也有了
1 | go复制代码 if i > 0 && c == scases[lockorder[i-1]].c { |
这部分当然也是为了防止重复解锁,不过作者在注释中特意强调了一定要注意不要重复解锁,因为一个通道在被解锁后可能就被释放了。
selparkcommit
1 | go复制代码func selparkcommit(gp *g, _ unsafe.Pointer) bool { |
gp.activeStackChans = true,第一行就看不懂了,查了下gp可以理解为是一个stack,activeStackChans表示有未锁定的通道指向这个协程的堆栈,当他为true的时候,代表如果进行堆栈复制的话需要我们先锁通道再进行堆栈复制。
atomic.Store是往第一个参数里写入第二个参数的值,是一个原子操作。store8代表参数类型为unit8。
ParkingOnChan 表示 goroutine 即将停在 chansend 或 chanrecv 上。 用于表示堆栈收缩的不安全点。 它是一个布尔值,但会原子的更新。
一旦我们解锁这个通道,该通道里任何sudog中的字段都有可能会更改,由于多个sudog可能有相同的通道,因此我们只有在通道的最后一个实例才可以解锁。
本文转载自: 掘金