golang之channel

版权声明:如有需要,可供转载,但请注明出处:https://blog.csdn.net/City_of_skey/article/details/86263168

目录

1、channel简介

2、channel阻塞

3、channel非阻塞

4、select


1、channel简介

go语言中并发程序非常简单直接用关键字go就可以起一个协程,go语言的协程是语言级别的所以它的开销比线程、进程要小,因为线程和进程是系统级别的并发。go语言协程同步可以通过channel来解决。

channel有三种类型:

var aa chan int        /*可读可写*/
var aa chan <- int     /*只能写*/
var aa <- chan int     /*只能读*/

channel类型必须先用make初始化再使用

aa := make(chan int)

关闭channel用函数close,一个关闭的channel还可以去读数据,但不能在写如数据,如果写入数据就会产生panic

aa := make(chan int)
close(aa)
aa <- 4    /*panic*/

 

 

2、channel阻塞

对于buffer为1的channel,从channel中读数据时当没有读到就会阻塞,向channel中写数据如果没有空间存储也会阻塞。

读阻塞:

aa := make(chan int)

b := <- aa    /*aa中没有数据就会阻塞*/

写阻塞:

aa := make(chan int)

aa <- 4
aa <- 5    /*4还没有取出来,channel中没有空间, 阻塞*/

3、channel非阻塞

当我们需要非阻塞的channel我们可以给channel分配空间,当空间没有填满channel不会阻塞,有buffer的channel相当于一个队列,遵循先进先出的规则。

aa := make(chan int, 4)

带buffer的channel读取可以用range。但要注意的是当channel中的数据被取完后就会阻塞,如果没有再往channel中写数据就会产生死锁

	w := make(chan int, 4)

	w <- 4
	w <- 5

	for b := range w {
        /*最后一个5取走后就会阻塞,产生死锁*/
		fmt.Printf("w:%d\n", b)
	}

避免死锁方法:

每次range读取数据后判断channel的长度,如果是0就说明channel为空,就应该退出。

w := make(chan int, 4)

	w <- 1
	w <- 2
	w <- 3
	w <- 4

	for b := range w {
		fmt.Printf("w:%d\n", b)
        
        /*如果channel长度是0就退出循环,不然会阻塞产生死锁*/
		if len(w) <= 0 {
			break
		}

	}

4、select

go中的select相当于c语言中的switch,是对对个channle做选择,它不是循环,如果要循环判断就要在外面在加一个for

package main

import (
	"fmt"
	"time"
)

func main() {
	a := make(chan int)
	b := make(chan int)
	defer close(a)
	defer close(b)

	go func() {
		for i := 1; i < 3; i++ {
			a <- i
			b <- (i + 1)
			time.Sleep(1 * time.Second)
		}

	}()

	for {
		select {
		case val1 := <-a:
			fmt.Println("val1:", val1)
		case val2 := <-b:
			fmt.Println("val2:", val2)
		case <-time.After(3 * time.Second): /*3秒超时*/
			fmt.Println("time out quit")
			return
		}
	}

}

select中可以加一个超时时间,超过这个时间通道中还没有数据就直接返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值