原创文章转载请注明出处
Go 运行时(runtime)管理了一种轻量级线程goroutine
,被叫做协程。协程可以使用共享变量来通信,但是很不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难。
不要通过共享内存来通信,它们会给你的代码在并发运算的时候带来危险,要通过通信来共享内存。
Go有一个特殊的类型,通道channel
像是管道,可以通过它们发送类型化的数据在协程之间通信,可以避开所有内存共享导致的坑;通道的通信方式保证了同步性。数据通过通道:同一时间只有一个协程可以访问数据:所以不会出现数据竞争,设计如此。数据的归属(可以读写数据的能力)被传递。
操作符 <- 被叫做 channel 操作符(这个操作符中箭头表明了值的流向)
// 发送 v 到 channel ch
ch <- v
// 接收 channel ch 中的值并赋值给 v
v := <-ch
燃鹅,channel是会阻塞的
func main() {
var c1 chan string = make(chan string)
func() {
time.Sleep(time.Second)
c1 <- "1"
}()
fmt.Println("c1 is", <-c1)
}
上面的例子中,push和pop永远不可能同时发生,会deadlock。
fatal error: all goroutines are asleep -
deadlock
!
goroutine 1 [chan send]:
main.main.func1(0xc42001e0c0)
/Users/mac/gowork/src/hello/hello.go:181 +0x63
main.main()
/Users/mac/gowork/src/hello/hello.go:182 +0x5b
exit status 2
如何实现非阻塞channel
- 利用
go
关键字,创建一个新的协程,让push和pop不在同一个协程中执行就可以避免死锁。
func main() {
var c1 chan string = make(chan string)
go func() {
time.Sleep(time.Second)
c1 <- "1"
}()
fmt.Println("c1 is", <-c1)
}
- 也可以给
channel
加一个buffer,当buffer没有被塞满的时候,channel
是不会阻塞的。
func main() {
var c1 chan string = make(chan string, 1)
func() {
time.Sleep(time.Second)
c1 <- "1"
}()
fmt.Println("c1 is", <-c1)
}
- 利用
select
给channel
添加默认处理
select
做的就是:选择处理列出的多个通信情况中的一个。
- 如果都阻塞了,会等待直到其中一个可以处理
- 如果多个可以处理,随机选择一个
- 如果没有通道操作可以处理并且写了
default
语句,它就会执行:default
永远是可运行的(这就是准备好了,可以执行)。
在select
中使用发送操作并且有 default可以确保发送不被阻塞!如果没有case
,select
就会一直阻塞。
func main() {
var c1 chan string = make(chan string)
var c2 chan string = make(chan string)
time.Sleep(time.Second)
select {
case c := <-c1:
fmt.Println(c)
case c := <-c2:
fmt.Println(c)
default:
fmt.Println("After one second!")
}
}
- 给
channel
添加超时处理,还是要用到select
func askForC(c chan string) {
fmt.Println("run in other routine")
}
func main() {
var c1 chan string = make(chan string)
var c2 chan string = make(chan string)
go askForC(c1)
go askForC(c2)
select {
case c := <-c1:
fmt.Println(c)
case c := <-c2:
fmt.Println(c)
case <-time.After(time.Second):
fmt.Println("After one second!")
}
}
我是咕咕鸡,一个还在不停学习的全栈工程师。
热爱生活,喜欢跑步,家庭是我不断向前进步的动力。