GO chan思绪整理(非缓冲chan)

初次学习go chan思路整理过程,当然也不免会碰到些低级错误

代码
package main

import "fmt"

func main() {
	ch := make(chan int)

	ch <- 20
	ch <- 21

	value := <-ch
	fmt.Printf("%s\n",value)

	value = <-ch
	fmt.Printf("%s\n",value)
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
	/Users/arno/go/src/go_study/goroutine/channel/channel1.go:9 +0x59
解释

chan是协程之间的数据传输的通道,但是这里只有一个主协程(main函数),所以会出现上面的错误。

说到协程这里也简单说明一下:
协程比线程更轻量级。协程也是宿主在线程中,一个线程可以包含多个协程。协程是非抢占式的,协程的所有权是主动交出的,所以它在切换时只需要记录点,而不会像线程那样要快照很多数据。

解决思路

加个协程试试,看代码

package main

import "fmt"

var ch1 chan int
func HelloChan()  {
	ch1 <- 20
	ch1 <- 21
}

func main() {
	ch1 = make(chan int)

	go HelloChan()

	value := <-ch1
	fmt.Printf("%d\n",value)

	value = <-ch1
	fmt.Printf("%d\n",value)
}

运行结果:

20
21

疑问:两个协程是怎么样配合的呢?
我稍改造代码试了一下,上代码:

package main

import (
	"fmt"
	"time"
)

var ch1 chan int
func HelloChan()  {
	ch1 <- 20
	fmt.Println("inner helloChan position 1")
	time.Sleep(time.Second*2)
	fmt.Println("间隔2秒后输出 :\n")
	fmt.Println("inner helloChan position 2")
	ch1 <- 21
	fmt.Println("inner helloChan position 3")
}

func main() {
	ch1 = make(chan int)

	go HelloChan()

	value := <-ch1
	fmt.Printf("%d\n",value)

	a:=0
	a++
	a++
	fmt.Println("other code ",a)

	value = <-ch1
	fmt.Printf("%d\n",value)
}

运行结果:

inner helloChan position 1
20
other code  2
间隔2秒后输出 :

inner helloChan position 2
inner helloChan position 3
21

根据结果分析运行流程:
GO chan思绪整理(非缓冲chan)_第1张图片

总结:

通篇说明了两个关键点:
1、chan是两个协程间通讯的,否则会报错,所以要注意某协程会提前结束导致报错
2、当协程读取chan时一定要读取到的,否则会被阻塞在这里
3、当协程向chan写入数据时,要等待被其它线程读取,否则也会阻塞。(关于这点我未加在上面的代码中,但我自己是实验过的,为了示例的简洁性,没加那么多复杂的逻辑进来)

篇外:

当有chan的交互时协程被阻塞,但是没有chan交互时协程间是相互不受影响的,来看一下代码:
package main

import (
	"fmt"
	"time"
)

func worker1()  {
	time.Sleep(time.Second*1)
	fmt.Println("worker1 :1 \n")
	time.Sleep(time.Second*1)
	fmt.Println("worker1 :2 \n")
	time.Sleep(time.Second*1)
	fmt.Println("worker1 :3 \n")
	time.Sleep(time.Second*1)
	fmt.Println("worker1 :4 \n")
}

func worker2()  {
	time.Sleep(time.Second*2)
	fmt.Println("worker2 :1 \n")
	time.Sleep(time.Second*2)
	fmt.Println("worker2 :2 \n")
}

func main() {
	go worker1()
	go worker2()

	time.Sleep(5*time.Second)
}

运行结果:

worker1 :1 
worker2 :1 
worker1 :2 
worker1 :3 
worker2 :2 
worker1 :4 

你可能感兴趣的:(golang)