golang--通过channel实现线程之间的通信

Channel:

一、channel简介

channel即通道,是goroutine沟通的桥梁,大都是阻塞同步的,是引用类型。

1、定义和创建channel;

channel的类型:chan + 数据类型,如:chan bool

创建channel:可以通过make函数来创建channel,第一个参数是channel的类型(如:chan bool),第二个参数是channel的缓存大小(可不填)。

示例如下:

var _channel chan bool    //声明channel

_channel := make(chan bool, 100)    //创建channel

2、通过close关闭;

close(_channel)

3、可以通过for range来迭代操作;

for v := range _channel {
	fmt.Println(v)
}

对线channel进行迭代操作时,必须在迭代的过程中明确关闭这个channel,并且保证channel被关闭成功!【调用close(_channel)】,否则会发生死锁,导致程序崩溃退出!

报错提示:fatal error: all goroutines are asleep - deadlock!

4、可以设置单向或双向通道;

双向通道:make创建的channel是双向通道,即channel值既可以存也可以取。

单向通道:分为两种:1、channel值只能存;2、channel值只能取。

5、可以设置缓存大小,在未被填满前不会发生阻塞;

无缓存是同步阻塞的,有缓存是异步的,这一点详细解释请看下一章【golang--channel缓存大小与线程阻塞的关系】

 

二、channel的具体操作实例:

1、通过channel来实现线程之间的通信;

完整代码如下:

package main

import (
	"fmt"
	"time"
)

func main() {
	_channel := make(chan bool)

	go func() {
		fmt.Println("新线程运行开始...")
        //让线程等待2秒
		time.Sleep(2 * time.Second)
		fmt.Println("新线程运行结束...")
		_channel <- true
	}()
	//main函数运行到这里,会发生阻塞,直到channel获得期待的值,才会继续往下运行.
	<-_channel
	//由于main函数执行完毕后,函数里的局部变量都会被释放,所以我们可以不对channel进行close操作.
	fmt.Println("main函数运行结束...")
}

运行结果如下:

新线程运行开始...
新线程运行结束...
main函数运行结束...

2、对channel进行迭代操作:

package main

import (
	"fmt"
	"time"
)

func main() {
	_channel := make(chan bool)

	go func() {
		fmt.Println("新线程运行开始...")
		//让线程等待2秒
		time.Sleep(2 * time.Second)
		fmt.Println("新线程运行结束...")
		_channel <- true
		//需要对channel执行关闭操作,否则在main函数中channel会一直进行迭代操作,永远处于阻塞状态,进而导致程序崩溃
		close(_channel)
	}()
	//main函数运行到这里时,会发生阻塞,等待channel获得期望的值
	for v := range _channel {
		//当channel获得期望的值时才会执行到这里
		fmt.Println("channel的值为:", v)
	}
	fmt.Println("main函数运行结束...")
}

运行结果如下:

新线程运行开始...
新线程运行结束...
channel的值为: true
main函数运行结束...

 

上一篇:8.3 Go channel


下一篇:【Groovy】闭包 Closure ( 闭包参数列表规则 | 默认参数列表 | 不接收参数 | 接收自定义参数 )