协程和线程的区别,协程特点如下:
- 该任务的业务代码主动要求切换,即主动让出所有权
- 发生了IO,导致执行阻塞。
##线程:
两个线程互相交替完成。
但是线程间切换的系统开销很大,需要保存上下文。
协程
CPU没有权利停止协程A,去执行协程B
只有以下两种情况
- 该任务的业务代码主动要求切换,即主动让出所有权
- 发生了IO,导致执行阻塞。(例如,协程A读文件或读channel阻塞,CPU会切换至协程B)
协程正常运行,CPU无法主动切换协程
package main
import (
"fmt"
"time"
"strconv"
)
func main(){
// 协程1
go func(){
for i := 0; i < 100; i++ {
fmt.Println("goroutine1: " + strconv.Itoa(i))
}
}()
// 协程2
go func(){
for i := 100; i < 200; i++{
fmt.Println("goroutine2: " + strconv.Itoa(i))
}
}()
time.Sleep(time.Second)
}
协程A主动出让所有权
等其他协程跑完时,再跑A协程剩下的。
package main
import (
"fmt"
"time"
"strconv"
"runtime"
)
func main(){
// 协程1
go func(){
for i := 0; i < 100; i++ {
if i == 10 {
runtime.Gosched()
}
fmt.Println("goroutine1: " + strconv.Itoa(i))
}
}()
// 协程2
go func(){
for i := 100; i < 200; i++{
fmt.Println("goroutine2: " + strconv.Itoa(i))
}
}()
time.Sleep(time.Second)
}
GOROOT=/usr/local/Cellar/go/1.9.2/libexec #gosetup
GOPATH=/Users/sunyuchuan/codes/my-go-codes:/Users/sunyuchuan/go #gosetup
/usr/local/Cellar/go/1.9.2/libexec/bin/go build -i -o /private/var/folders/s0/0gwfh5px0g1708zytjxl2b680000gn/T/___go_build_main_go /Users/sunyuchuan/codes/my-go-codes/bfchannel/main.go #gosetup
/private/var/folders/s0/0gwfh5px0g1708zytjxl2b680000gn/T/___go_build_main_go #gosetup
goroutine2: 100
goroutine2: 101
goroutine2: 102
goroutine2: 103
goroutine2: 104
goroutine2: 105
goroutine2: 106
goroutine2: 107
goroutine2: 108
goroutine2: 109
goroutine2: 110
goroutine2: 111
goroutine2: 112
goroutine2: 113
goroutine2: 114
goroutine2: 115
goroutine2: 116
goroutine2: 117
goroutine2: 118
goroutine2: 119
goroutine2: 120
goroutine1: 0
goroutine1: 1
goroutine1: 2
goroutine1: 3
goroutine1: 4
goroutine1: 5
goroutine1: 6
goroutine1: 7
goroutine1: 8
goroutine1: 9
goroutine2: 121
goroutine2: 122
goroutine2: 123
goroutine1: 10
goroutine1: 11
goroutine1: 12
goroutine1: 13
goroutine1: 14
goroutine1: 15
goroutine1: 16
goroutine1: 17
goroutine1: 18
goroutine1: 19
goroutine1: 20
goroutine1: 21
goroutine1: 22
goroutine1: 23
goroutine1: 24
goroutine1: 25
goroutine1: 26
goroutine1: 27
goroutine1: 28
goroutine1: 29
goroutine1: 30
goroutine1: 31
goroutine1: 32
goroutine1: 33
goroutine1: 34
goroutine1: 35
goroutine1: 36
goroutine1: 37
goroutine1: 38
goroutine1: 39
goroutine1: 40
goroutine1: 41
goroutine2: 124
goroutine2: 125
goroutine2: 126
goroutine2: 127
goroutine2: 128
goroutine2: 129
goroutine2: 130
goroutine2: 131
goroutine2: 132
goroutine1: 42
goroutine1: 43
goroutine1: 44
goroutine1: 45
goroutine1: 46
goroutine1: 47
goroutine1: 48
goroutine1: 49
goroutine1: 50
goroutine1: 51
goroutine1: 52
goroutine1: 53
goroutine1: 54
goroutine1: 55
goroutine1: 56
goroutine1: 57
goroutine1: 58
goroutine1: 59
goroutine1: 60
goroutine1: 61
goroutine1: 62
goroutine1: 63
goroutine1: 64
goroutine1: 65
goroutine1: 66
goroutine1: 67
goroutine1: 68
goroutine1: 69
goroutine1: 70
goroutine1: 71
goroutine1: 72
goroutine1: 73
goroutine1: 74
goroutine1: 75
goroutine1: 76
goroutine1: 77
goroutine1: 78
goroutine2: 133
goroutine2: 134
goroutine2: 135
goroutine2: 136
goroutine2: 137
goroutine2: 138
goroutine2: 139
goroutine2: 140
goroutine2: 141
goroutine2: 142
goroutine2: 143
goroutine2: 144
goroutine2: 145
goroutine2: 146
goroutine2: 147
goroutine2: 148
goroutine2: 149
goroutine2: 150
goroutine2: 151
goroutine2: 152
goroutine2: 153
goroutine2: 154
goroutine2: 155
goroutine2: 156
goroutine2: 157
goroutine2: 158
goroutine2: 159
goroutine2: 160
goroutine2: 161
goroutine1: 79
goroutine1: 80
goroutine1: 81
goroutine1: 82
goroutine1: 83
goroutine1: 84
goroutine1: 85
goroutine1: 86
goroutine1: 87
goroutine1: 88
goroutine1: 89
goroutine1: 90
goroutine1: 91
goroutine1: 92
goroutine1: 93
goroutine1: 94
goroutine1: 95
goroutine1: 96
goroutine1: 97
goroutine1: 98
goroutine1: 99
goroutine2: 162
goroutine2: 163
goroutine2: 164
goroutine2: 165
goroutine2: 166
goroutine2: 167
goroutine2: 168
goroutine2: 169
goroutine2: 170
goroutine2: 171
goroutine2: 172
goroutine2: 173
goroutine2: 174
goroutine2: 175
goroutine2: 176
goroutine2: 177
goroutine2: 178
goroutine2: 179
goroutine2: 180
goroutine2: 181
goroutine2: 182
goroutine2: 183
goroutine2: 184
goroutine2: 185
goroutine2: 186
goroutine2: 187
goroutine2: 188
goroutine2: 189
goroutine2: 190
goroutine2: 191
goroutine2: 192
goroutine2: 193
goroutine2: 194
goroutine2: 195
goroutine2: 196
goroutine2: 197
goroutine2: 198
goroutine2: 199
Process finished with exit code 0
运行效果不对
协程A阻塞,协程B先运行,等阻塞恢复后,协程A再继续
package main
import (
"fmt"
"time"
"strconv"
// "runtime"
)
var ch chan int
func main(){
// 协程1
go func(){
for i := 0; i < 100; i++ {
if i == 10 {
// runtime.Gosched()
<-ch // 读无值的chan
}
fmt.Println("goroutine1: " + strconv.Itoa(i))
}
}()
// 协程2
go func(){
for i := 100; i < 200; i++{
fmt.Println("goroutine2: " + strconv.Itoa(i))
}
ch <- 1 // 协程2结束,开始协程1
}()
time.Sleep(time.Second)
}
运行效果也不对