golang学习笔记-channel

channel简介

多线程传递数据的方式一般是通过共享内存,为了解决线程的竞争,需要限制同一时间访问这些线程的数量(互斥锁)。

golang采用channel(通道)进行协程间的数据传递,信道分为无缓冲通道和有缓冲通道,对于无缓冲通道来说,发送消息和接收消息都是阻塞的。无缓冲通道在发送和接受消息时协程出于挂起的状态,除非另一端准备好,否则协程是无法继续执行下去的。

channel的应用

代码1演示如下

package main

import (
	"fmt"
	"time"
)

func main() {

	ch := make(chan string)
	//发送操作在协程中执行,如不在协程中操作,则主函数报错
	go send(ch,"test")
	go recv(ch)
	time.Sleep(time.Second)
    
    //循环发送消息
    ch1 := make(chan int)
	go func() {
		for i:=0;i<=5 ;i++  {
				fmt.Println("这是写入的",i)
				ch1 <- i
		}
	}()
	go func() {
	    //for循环遍历channel数据
		for i:=range ch1 {
			fmt.Println("这是读取的",i)
		}
	}()
	//关闭通道
	defer close(ch1)
    
}

func send(ch chan string,cnt string) {
	ch <- cnt
}

func recv(ch chan string) {
	fmt.Println(<-ch)
}

死锁deadlock

当main函数执行到send方法时就变成挂起状态,而且并没有其他的协程来负责接受消息,下一行的代码永远无法执行,系统会自动判断为超时而抛出异常。这种所有线程或者集成都在等待资源释放的情况,我们成为死锁 deadlock

关于死锁的演示代码2如下所示

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan string)
	send(ch,"test")
	time.Sleep(time.Second)
}

func send(ch chan string,content string) {
	ch <- content
}

func recv(ch chan string) {
	fmt.Println(<-ch)
}

程序执行结果:

[root@d312d24bef6f day1118]# go run main.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.send(...)
	/data/webroot/go/test/day1118/main.go:17
main.main()
	/data/webroot/go/test/day1118/main.go:11 +0x65
exit status 2

解决方式:
1,写操作在在协程中执行如代码1中展示
2,写操作非协程时,在写操作前加一个协程的读操作 代码3如下

func main() {
	ch := make(chan string)
	go recv(ch)
	send(ch,"test")
	time.Sleep(time.Second)
}

3,创建channel为缓冲通道,缓冲通道就是存储数据的channel,通过make函数的长度参数(默认为0说明不能存储数据,写入后会发生阻塞,直到数据被读取)来控制。
代码4如下

func main() {
	ch := make(chan string,1)
	send(ch,"test")
	recv(ch)
	time.Sleep(time.Second)
}
单向通道
package main

import (
	"fmt"
	"time"
)

func main() {
    var sendOnlyCh chan<- string //单向发送通道
    var recvOnlyCh <-chan string //单向接受通道
    
    ch := make(chan string)
    sendOnlyCh = ch
    recvOnlyCh = ch
    
    go sendOnly(sendOnlyCh)
    
    go reacOnly(recvOnlyCh)
    
    time.Sleep(time.Second)
}

func sendOnly(ch chan<- string){
    ch <- "hahaha"
}

func reacOnly(ch <-chan string){
    fmt.Println(<-ch)
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值