并发编程概览

并行和并发

并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。

并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。

  • 并行是两个队列同时使用两台咖啡机
  • 并发是两个队列交替使用一台咖啡机

并行:不同的执行单位,看起来是一起执行的,但是微观上还是串行的。

并发:多核CPU同时执行。

进程 线程 协程

进程是资源分配的单元,线程是调度的单元。

协程是用户态的,只是将待执行的程序用堆栈维护起来,然后在同一个线程上交替执行,只是并行,不是并发。

多线程,需要CPU和内核层的上下文切换,切换的是时间片。

多进程,不仅是时间片,还有资源调度,更麻烦。

多进程的好处是数据隔离,A崩了不影响B。

多线程是共享数据的,进程间通信会比较方便。

进程间通信方式:

管道,消息队列,信号量,Socket,Streams 等。

(这些都是通过共享内存来通讯,而GO是利用通信来共享内存。)

什么是协程

线程遇到阻塞函数,只能挂起,切到别的线程,为了减少切换成本,java可以用异步回调。

异步回调确实不用阻塞,不过它有两个弊端,

  • 其一:割裂了原来的代码业务逻辑。
  • 其二:陷入回调地狱难以维护。

而Go采用了线程的思路:

线程可以在遇到阻塞的地方后,保存执行的上下文,转而去执行别处的代码。

待阻塞的请求完成后,再转而回去继续执行。

函数执行到一半还能中途退出再回来?

线程执行函数中途,遇到时间片用完或者遇到I/O阻塞,就会被操作系统保存上下文后挂起,切换到其他线程。而后等到机会再回过头继续执行,不是吗?

既然操作系统可以调度管理多个线程,那为何线程不可以调度管理函数的执行?


线程是操作系统抽象出来的执行流,由操作系统统一调度管理。

那在一个线程中,同样可以抽象出多个执行流,由线程来统一调度管理。这线程之上抽象的执行流就是协程。

线程:

协程:

线程的调度由操作系统来管理,是抢占式调度。

而协程不同,协程需要互相配合,主动交出执行权,这也是协程的名字——协作式程序的来历。

欢迎来我的语雀空间:www.yuque.com/lixin-fjgsf…

Guess you like

Origin juejin.im/post/7075540285626957837