- 进程、线程、协程区别
=============
a. 各自特点
参考《详细介绍 进程、线程和协程的区别》
- 进程:拥有自己独立的堆和栈,既不共享堆,也不共享栈,进程由操作系统调度;
- 线程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,标准线程由操作系统调度;
- 协程:拥有自己独立的栈和共享的堆,共享堆,不共享栈,协程由程序员在协程的代码里显示调度。
协程与线程:
每个单位时间内,一个 CPU 只能处理一个线程(操作系统:thread),线程是 CPU 处理的单位或单元,底层资源占用中等(比进程少)。线程中程序的执行过程是:同步阻塞的(依次执行),非抢占式的(依代码编写顺序)。开发上比较清晰明了。
协程是“用户级”的线程,通过把线程的分段运行:主动暂停、主动运行,切换逻辑点,针对 i / o 请求可以节约连接、对方处理的中间环节等待时间,一个线程上可以跑多个协程。协程中的程序执行是触发、跳转的,异步非阻塞的(事件触发),抢占式的(线程挂起等待响应)。开发上很复杂。
b. 上代码
go 协程
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
)
type array2j struct {a []string
b string
}
func main() {ch := make(chan string, 3)
c2 := make(chan string)
var queue array2j
for i:=1; i<=5; i++ {go func(i int) {fmt.Println("go func:" + strconv.Itoa(i))
ch <- strconv.Itoa(i) + "_ch_" + strconv.Itoa(rand.Int())
}(i)
}
for j:=1; j<=2; j++ {go func() {time.Sleep(1 * time.Second)
ch <- "c2"
}()}
time.Sleep(1 * time.Second)
for {
select {
case a,e := <-ch:
fmt.Println(a,e)
queue.a = append(queue.a, a)
case b,e := <-c2:
fmt.Println(b,e)
queue.b = b
}
if len(ch) + len(c2) == 0 {fmt.Println("queue", queue)
break
}
res, err := <- ch
fmt.Println(res, err)
}
fmt.Println("hello go!")
}
/**
go func:1
go func:4
go func:2
go func:3
go func:5
1_ch_5577006791947779410 true
4_ch_8674665223082153551 true
2_ch_6129484611666145821 true
3_ch_4037200794235010051 true
5_ch_3916589616287113937 true
c2 true
c2 true
queue {[1_ch_5577006791947779410 4_ch_8674665223082153551 2_ch_6129484611666145821 3_ch_4037200794235010051 5_ch_3916589616287113937 c2 c2] }
hello go!
*/