Thread 线程
在传统的web编程中,经常要用到多线程。比如 java,来一个websocket 即开启一个thread(线程)。
而thread的数目是有限的,一般的电脑可以同时开的thread数量大概几千个。而GO语言可以开启的goroutine,却可以达到几百万个,因此很显然goroutine不等于thread。
那么Thread和Goroutine的区别是什么?
Thread,即多个程序切换执行
示例代码:
线程1
thread1(){
for i = 1:10
print("Thread1 : ",i)
}
线程2
thread1(){
for i = 1:10
print("Thread2 : ",i)
}
执行结果是:
thread1 : 1
thread2 : 1
thread1 : 2
thread2 : 2
thread1 : 3
thread2 : 3
thread1 : 4
thread2 : 4
thread1 : 5
thread2 : 5
可以看到两个thread交替执行,最后产生同时执行的效果
Goroutine 协程
而协程则完全不是这么一回事,协程是不切换的,执行完协程A,再执行协程B
协程切换的条件有两个
- 该协程主动要求切换给其他协程
- 该协程执行时遇到堵塞,比如在等待 IO 读数据,或者读channel时陷入等待,这样就会被CPU强行切换到其他协程
代码测试
package main
import (
"fmt"
"time"
)
func routineA() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine A : %d\n", i)
}
}
func routineB() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine B : %d\n", i)
}
}
func main() {
go routineA()
go routineB()
time.Sleep(time.Second * 2)
}
测试结果
很显然,goroutine A执行完,然后才执行 goroutine B
测试第一个特性
该协程主动要求切换给其他协程
使用的代码 runtime.Gosched()
package main
import (
"fmt"
"runtime"
"time"
)
func routineA() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine A : %d\n", i)
if 3 == i {
runtime.Gosched()
}
}
}
func routineB() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine B : %d\n", i)
}
}
func main() {
go routineA()
go routineB()
time.Sleep(time.Second * 2)
}
结果
测试第二个特性
该协程执行时遇到堵塞,比如在等待 IO 读数据,或者读channel时陷入等待,这样就会被CPU强行切换到其他协程
使用channel的读写作为测试,代码如下
package main
import (
"fmt"
"time"
)
var ch chan int
func routineA() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine A : %d\n", i)
if 3 == i {
a := <-ch
fmt.Printf("Goroutine A : read channal value %d\n", a)
}
}
}
func routineB() {
for i := 1; i <= 5; i++ {
fmt.Printf("Goroutine B : %d\n", i)
if 4 == i {
ch <- 3
fmt.Printf("Goroutine B : write channal value\n")
}
}
}
func main() {
ch = make(chan int)
go routineA()
go routineB()
time.Sleep(time.Second * 2)
}
执行结果
|
请发表评论