goroutine 是 go语言里的轻量级线程,仅仅利用 go 就能立刻起一个新线程。多线程之间的同步问题,在 go语言 中可以使用 channel 作为同步的工具。通过 channel 通道可以实现两个 goroutine 之间的通信。创建通道的方法使用make函数,如:make(chan 类型,num),这里的第二个参数就是要创建的通道数目,写入通道用:通道名字<-要写入的数值,从通道读取数据用:返回值<-通道名字
package main
import (
"fmt"
"time"
)
func fun1(tc chan int) {
time.Sleep(10000 * time.Millisecond) //延时10秒
fmt.Println("线程func1结束")
tc<-1 //向通道里写入一个数据1
close(tc)//关闭通道并不会丢失里面的数据,只是让读取通道数据的时候不会读完之后一直阻塞。
}
func fun2(tc chan int) {
time.Sleep(5000 * time.Millisecond)//延时5秒
fmt.Println("线程func2结束")
tc<-2 //向通道里写入一个数据2
}
func main() {
c:=make(chan int,2)
go fun1(c)
go fun2(c)
fmt.Println("等待2个线程执行...")
for rt:= range c {
fmt.Println("等待到线程结束:",rt)
}
}
可以看到,通过range遍历通道的值后,会依次读取写入通道的值。在最后close关闭通道后,range遍历就会停止。
这里,再把上边例子修改下:
package main
import (
"fmt"
"time"
)
func fun1(tc chan int) {
fmt.Println("线程func1开始写入管道")
tc<-1
tc<-1
fmt.Println("线程func1结束")
}
func fun2(tc chan int) {
time.Sleep(2000 * time.Millisecond)//延时3秒
fmt.Println("线程func2开始写入管道")
tc<-2
tc<-2
fmt.Println("线程func2结束")
close(tc) //关闭通道,读取通道将退出
}
func main() {
c:=make(chan int,2)
go fun1(c)
go fun2(c)
fmt.Println("等待2个线程执行...")
time.Sleep(6000 * time.Millisecond) //延时6秒
for rt:= range c {
fmt.Println("等待到线程结束:",rt)
}
}
可以看到,这里是主程序开启2个线程后,先等待6秒。第1个线程先依次向2个管道写入数值,然后退出。而第2个线程等待3秒后开始写入管道,不过这时主程序还没从管道里读取,所以线程2是阻塞在等待。当主程序等待时间结束,开始从管道里依次读取后,线程2就可以写入管道了,在线程2一开始写入,主程序就能立即读取到。最后线程2调用close关闭管道,主程序就从遍历通道过程中结束了。