Jump to Navigation

Go 语言 select代码块的执行过程:(译)

Go 语言 select代码块的执行过程:(译)

1、求值所有的channel和可能会发送的值,从上到下,从左到右。

2、随机排序所有的case分支(默认分支当作特殊case)。The corresponding channels of the orders may be duplicate. 默认分支总是放在最后的位置。

3、排序所有的channel以避免下一步的死锁。排列列表中不存在重复的channel。

4、锁定上一步中涉及的所有的channel。

5、以随机的case分支顺序轮循每个分支:

1、如果对应的channel操作是“发送值到关闭的channel”,解锁所有的channel并panic。进入12步。

2、如果对应的channel操作是非阻塞的,执行该channel操作并解锁所有 的channel,然后执行对应的分支。
该channel操作可能唤醒另量个阻塞的goroutine。进入12步。

3、如果分支是默认分支,那么解锁所有的channel并执行分支。进入12步。

6、把当前的goroutine(附带case channel的操作信息)放入每个case操作涉及的channel的接收或发送goroutine队列。
当前goroutine可能会重复放入channel的队列,因为多个case中涉及的多个channel可能是同一个。

7、阻塞当前goroutine并以排序锁定的顺序解锁所有的channels。

8、在阻塞的状态下,等待其他的channel操作唤醒当前的goroutine

9、当前goroutine被另一个goroutine中的channel操作唤醒。channel操作可能是关闭、读写操作。如果是发送/接收操作,
必须有一个对应的channel接收/发送操作,当前goroutine必须从接收/发送的goroutine的channel中出队。

10、以排序锁定的顺序锁定所有涉及的channel.

11、从每个case操作涉及的channel的接收/发送队列出队当前goroutine:

1、如果当前goroutine是被一个channel的close操作唤醒,则转到第5步。
2、如果当前goroutine是被一个channel的发送/接收操作唤醒,相应接收/发送操作对应的case分支已经在出队过程,
那么只需以排序锁定顺序解锁所有的channels,并执行对应的case分支。

12、完成。

参考: http://www.tapirgames.com/blog/golang-concurrent-select-implementation
https://www.reddit.com/r/golang/comments/63m6ou/resources_for_deeper_und...

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.


Main menu 2

Story | by Dr. Radut