Skip to content

Commit

Permalink
Merge pull request aceld#5 from tangx/main
Browse files Browse the repository at this point in the history
docs: 更新文档描述及typo错误
  • Loading branch information
aceld authored Mar 6, 2023
2 parents 92751ab + 5b67179 commit a533790
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,21 @@

协程切换比线程切换快主要有两点:

(1)协程切换**完全在用户空间进行**线程切换涉及**特权模式切换,需要在内核空间完成**
(1)协程切换**完全在用户空间进行**线程切换涉及**特权模式切换,需要在内核空间完成**

(2)协程切换相比线程切换**做的事情更少**,线程需要有内核和用户态的切换,系统调用过程。



#### 协程切换成本:

协程切换非常简单,就是把**当前协程的 CPU 寄存器状态保存起来,然后将需要切换进来的协程的 CPU 寄存器状态加载的 CPU 寄存器上**就 ok 了。而且**完全在用户态进行**,一般来说一次协程上下文切换最多就是**几十ns** 这个量级。
协程切换非常简单,就是把**当前协程的 CPU 寄存器状态保存起来,然后将需要切换进来的协程的 CPU 寄存器状态加载到 CPU 寄存器上**就 ok 了。而且**完全在用户态进行**,一般来说一次协程上下文切换最多就是**几十ns** 这个量级。



#### 线程切换成本:

系统内核调度的对象是线程,因为线程是调度的基本单元(进程是资源拥有的基本单元,进程的切换需要做的事情更多,这里占时不讨论进程切换),而**线程的调度只有拥有最高权限的内核空间才可以完成**,所以线程的切换涉及到**用户空间和内核空间的切换**,也就是特权模式切换,然后需要操作系统调度模块完成**线程调度(task***struct),*而且除了和协程相同基本的 CPU 上下文,还有线程私有的栈和寄存器等,说白了就是上下文比协程多一些,其实简单比较下 task_strcut 和 任何一个协程库的 coroutine 的 struct 结构体大小就能明显区分出来。而且特权模式切换的开销确实不小,随便搜一组测试数据 [3],随便算算都比协程切换开销大很多。
系统内核调度的对象是线程,因为线程是调度的基本单元(进程是资源拥有的基本单元,进程的切换需要做的事情更多,这里占时不讨论进程切换),而**线程的调度只有拥有最高权限的内核空间才可以完成**,所以线程的切换涉及到**用户空间和内核空间的切换**,也就是特权模式切换,然后需要操作系统调度模块完成**线程调度(task_struct)**而且除了和协程相同基本的 CPU 上下文,还有线程私有的栈和寄存器等,说白了就是上下文比协程多一些,其实简单比较下 task_strcut 和 任何一个协程库的 coroutine 的 struct 结构体大小就能明显区分出来。而且特权模式切换的开销确实不小,随便搜一组测试数据 [3],随便算算都比协程切换开销大很多。



Expand Down Expand Up @@ -222,7 +222,7 @@ KiB Swap: 969960 total, 563688 free, 406272 used. 168812 avail Mem

free的mem为1675844,

所以**20万个协程占用了约 50万KB****平均一个协程占用约2.5KB**
所以 **20万个** 协程占用了约 **50万KB**, **平均** 一个协程占用约 **2.5KB**



Expand Down
9 changes: 4 additions & 5 deletions 5、channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@

* 给一个已经关闭的 channel 发送数据,引起 panic

* 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
* 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回 **一个零值 和 false** (ex: `val,ok:= <-ch1`)

* 无缓冲的channel是同步的,而有缓冲的channel是非同步的

以上5个特性是死东西,也可以通过口诀来记忆:“空读写阻塞,写关闭异常,读关闭空零”。


以上5个特性是死东西,也可以通过口诀来记忆:“读写****阻塞,写**关闭**异常,读**关闭空**零假”。

![](images/169-channel异常情况总结.png)


> 执行下面的代码发生什么?
Expand Down Expand Up @@ -59,7 +58,7 @@ func main() {



15字口诀:“空读写阻塞,写关闭异常,读关闭空零”,往已经关闭的channel写入数据会panic的。因为main在开辟完两个goroutine之后,立刻关闭了ch, 结果:
15字口诀:“读写****阻塞,写**关闭**异常,读**关闭空**零假”,往已经关闭的channel写入数据会panic的。因为main在开辟完两个goroutine之后,立刻关闭了ch, 结果:

```
panic: send on closed channel
Expand Down
Binary file added images/169-channel异常情况总结.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a533790

Please sign in to comment.