Skip to content

Commit a533790

Browse files
authored
Merge pull request aceld#5 from tangx/main
docs: 更新文档描述及typo错误
2 parents 92751ab + 5b67179 commit a533790

File tree

3 files changed

+8
-9
lines changed

3 files changed

+8
-9
lines changed

3、对于操作系统而言进程、线程以及Goroutine协程的区别.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,21 @@
9393

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

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

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

100100

101101

102102
#### 协程切换成本:
103103

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

106106

107107

108108
#### 线程切换成本:
109109

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

112112

113113

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

223223
free的mem为1675844,
224224

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

227227

228228

5、channel.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212

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

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

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

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

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

2423

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

6059

6160

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

6463
```
6564
panic: send on closed channel
968 KB
Loading

0 commit comments

Comments
 (0)