Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用 CPU 性能。
多个 goroutine 中,Go语言使用通道(channel)进行通信,通道是一种内置的数据结构,可以让用户在不同的 goroutine 之间同步发送具有类型的消息。这让编程模型更倾向于在 goroutine 之间发送消息,而不是让多个 goroutine 争夺同一个数据的使用权。
程序可以将需要并发的环节设计为生产者模式和消费者的模式,将数据放入通道。通道另外一端的代码将这些数据进行并发计算并返回结果
package main
import (
"fmt" // I/O格式化
"math/rand" // 随机数
"time" // 时间
)
/* 生产者每秒生成一个字符串,并通过通道传给消费者,生产者使用两个 goroutine 并发运行,
消费者在 main() 函数的 goroutine 中进行处理。 */
//数据生产者
//
func producer(header string,channel chan<-string) {
//无限循环,生产数据
for{
//将随机数和字符串格式化为字符串发送(指向)给通道
channel<-fmt.Sprintf("%s:%v",header,rand.Int31())
time.Sleep(time.Second) //sleep 1s
}
}
//数据消费者,传入一个只能写入的通道。(单向通道)
func customer(channel<-chan string) {
//循环获取数据
for{
//从通道中取出数据, 此处会阻塞直到信道中返回数据
messages:=<-channel
//打印数据
fmt.Println(messages)
}
}
//主程序入口
func main() {
//创建一个字符串类型的通道 chan: 引用传值
channel:=make(chan string)//二级信号(类似二级指针)
//创建生产者producer()函数的并发goroutine (搭配2个不同参数)
go producer("cat",channel)
go producer("dog",channel)
//执行消费数据函数通过通道进行数据消费
customer(channel)
}
/*整段代码中,没有线程创建,没有线程池也没有加锁,仅仅通过关键字 go 实现 goroutine,和通道实现数据交换。*/