go 信道chan有缓冲通道跟无缓冲通道区别:

go通道chan:
通道(channel)是用来传递数据的一个数据结构,通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯,操作符 <- 用于指定通道的方向,发送或接收,如果未指定方向,则为双向通道。
1、无缓冲:
要求发送方和接收方的goroutine同时准备好,才能完成发送和接收操作。
如果两个goroutine都没有准备好,通道会导致先执行发送或者接收的goroutine阻塞等待,这种对通道进行发送跟接收的交互行为本身就是同步的。

2:有缓冲的通道:
缓冲信道的容量:
是指信道可以存储的值的数量。我们在使用 make 函数创建缓冲信道的时候会指定容量大小。

缓冲信道的长度:是指信道中当前排队的元素个数。

一种在被接收前能存储一个或多个值的通道。并不强制goroutine直接必须同时完成发送和接收,只有通道中没有要接收的值时,接收动作才会阻塞,只有在通道没有可用的缓冲区容纳被发送的值时,发送动作才会阻塞。

带缓冲通道在很多特性上和无缓冲通道是类似的。无缓冲通道可以看作是长度永远为 0 的带缓冲通道。因此根据这个特性,带缓冲通道在下面列举的情况下依然会发生阻塞:
1、带缓冲通道被填满时,尝试再次发送数据时发生阻塞。
2、带缓冲通道为空时,尝试接收数据时发生阻塞。

channel存在3种状态:

  1. nil,未初始化的状态,只进行了声明,或者手动赋值为nil ;
  2. active,正常的channel,可读或者可写 ;
  3. closed,已关闭,千万不要误认为关闭channel后,channel的值是nil,关闭的状态的chan仍然可以读值(取值),但不能写值(会报panic: send on closed channel),nil状态的chan是不能close(panic: close of nil channel)。
func main() {
	var a chan int
	fmt.Println(a) // <nil>
	a = make(chan int)
	close(a)
	fmt.Println(a) // 0xc00003e060
}

channel可进行3种操作:
1、读;
2、写;
3、关闭。
在这里插入图片描述
对于nil通道的情况,也并非完全遵循上表,有1个特殊场景:当nil的通道在select的某个case中时,这个case会阻塞,但不会造成死锁。

下面介绍使用channel的10种常用操作:

  1. 使用for range读channel

场景:当需要不断从channel读取数据时
原理:使用for-range读取channel,这样既安全又便利,**当channel关闭时,for循环会自动退出,**无需主动监测channel是否关闭,可以防止读取已经关闭的channel,造成读到数据为通道所存储的数据类型的零值。
注意:只适合有缓冲chan

var syn sync.WaitGroup
var sss int

func main() {
	sss = 2
	syn.Add(1)
	a := make(chan int, sss)
	a <- 4
	a <- 8
	go Aaa(a)
	syn.Wait()
}

func Aaa(a chan int) {
	defer syn.Done()
	for x := range a {
		sss--
		if sss == 0 {
			close(a)
		}
		fmt.Println("==", x)
	}
}
  1. 使用_,ok判断channel是否关闭

场景:读channel,但不确定channel是否关闭时
原理:读已关闭的channel会造成零值 ,如果不确定channel,需要使用ok进行检测。ok的结果和含义:
true:读到数据,并且通道没有关闭。
false通道关闭,且无数据读到。

注意:只适合有缓冲chan

var syn sync.WaitGroup
var sss int

func main() {
	sss = 2
	syn.Add(1)
	a := make(chan int, sss)
	a <- 405
	close(a)
	go Aaa(a)
	syn.Wait()
}

func Aaa(a chan int) {
	defer syn.Done()
	for {
		v, ok := <-a
		fmt.Println(v, ok)
		if !ok {
			break
		}
	}
}

输出:

405 true
0 false

3、读写

package main

import (
	"fmt"
	"time"
)

func WriteData(intChan chan int)  {
	for i:=1;i<=50;i++{
		intChan<-i
		fmt.Println("写:",i)
		time.Sleep(time.Millisecond*100)
	}
	close(intChan) //写完后关闭管道
}

func ReadData(intChan chan int,exitChan chan bool)  {
	for{
		v,ok:=<-intChan
		if !ok{
			fmt.Println("读取完毕")
			break
		}
		fmt.Println("读:",v)
	}

	//设置全局标志 告诉main 读取完毕了 main主线程可以关闭了
	exitChan<-true
	close(exitChan)
}

func main() {

	intChan :=make(chan int,50)
	exitChan:=make(chan bool,1)

	go WriteData(intChan)
	go ReadData(intChan,exitChan)

	//阻塞主线程
	for ok:=range exitChan{
		fmt.Println(ok)
	}
}

4、管道实现互斥锁

var counter = 0

func Increase1000(id int, done chan bool, mutex chan bool) {
	for i := 0; i < 1000; i++ {
		mutex <- true //加锁
		counter += 1
		time.Sleep(time.Microsecond)
		<-mutex //解锁
	}
	done <- true
}

func main() {
	mutex, done := make(chan bool, 1), make(chan bool)
	go Increase1000(1, done, mutex)
	go Increase1000(2, done, mutex)

	<-done
	<-done
	log.Println(counter)
}

5、管道实现定时通知
注意:有缓冲和无缓冲通道都可以实现

func Notice(d time.Duration, c chan bool) chan bool {
	time.Sleep(d) //定时
	c <- true
	return c
}

func main() {
	c := make(chan bool)
	log.Println("one")
	go Notice(time.Second, c)
	<-c //管道没有写则阻塞
	log.Println("tow")
	go Notice(time.Second, c)
	<-c
	log.Println("three")
}
func Notice(d time.Duration) chan bool {
	c := make(chan bool, 1)
	time.Sleep(d) //定时
	c <- true
	close(c)
	return c
}

func main() {
	log.Println("one")
	<-Notice(time.Second) //管道没有写则阻塞
	log.Println("tow")
	<-Notice(time.Second)
	log.Println("three")
}

6、通过两个 goroutine 来计算数字之和

package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // 把 sum 发送到通道 c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0, 8, 6, 78}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c // 从通道 c 中接收

	fmt.Println(x, y, x+y)
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
通道和多通道是指在软件无线电中用于传输和接收无线信号的通道数量。 单通道指的是只有一个信道用于传输和接收无线信号。这意味着在同一时间内,只能处理一个信号,无法同时进行多个通信任务。单通道通常用于低复杂度的应用,例如简单的语音通信或数据传输。 多通道则指的是有多个信道同时用于传输和接收无线信号。这意味着在同一时间内,可以处理多个信号,支持同时进行多个通信任务。多通道通常用于复杂的应用,如同时进行多个语音通话或数据传输任务。 区别主要体现在以下几个方面: 1. 同步性能:多通道可以同时处理多个信号,因此具有更好的并发处理能力,可以提供更高的吞吐量和更低的延迟。 2. 频谱利用率:多通道可以更有效地利用频谱资源,避免频谱浪费。而单通道只能使用一部分频谱资源。 3. 系统复杂度:多通道系统通常比单通道系统更复杂,需要更多的硬件和软件支持。而单通道系统相对简单且成本较低。 4. 应用场景:单通道适用于简单的通信需求,而多通道更适用于需要同时处理多个信号的复杂应用场景。 综上所述,单通道和多通道在软件无线电中主要区别在于处理能力、频谱利用率、系统复杂度和适用场景等方面。选择单通道还是多通道取决于具体的应用需求和资源限制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心码农1号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值