golang基础教程(十六)goroutine 和 channel使用_golang goruntine chan一起使用

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

golang基础教程

一、Go 协程和 Go 主线程

Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以
这样理解,协程是轻量级的线程[编译器做优化]
Go 协程的特点

  1. 有独立的栈空间
  2. 共享程序堆空间
  3. 调度由用户控制
  4. 协程是轻量级的线程

二、goroutine使用

1、一个简单的案例

  1. 在主线程(可以理解成进程)中,开启一个 goroutine, 该协程每隔 1 秒输出 “hello,world”
  2. 在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序
    同时进行
func test(){
	for i:=0;i<10;i++{
		time.Sleep(time.Second)
		fmt.Println("hello world")
	}
}
func main() {
	go test()
	for i:=0;i<10;i++{
		time.Sleep(time.Second)
		fmt.Println("hello golang")
	}
}


2、总结:

  1. 主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。
  2. 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
  3. Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一
    般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了

三、channel使用

1、为什么用channel

异步累加案例:

var s =0

func sum(a int){
	s+=a
}
func main() {
	for i:=0;i<100;i++{
		go sum(i)
	}
	time.Sleep(time.Second\*2)
	fmt.Println(s)
}

每次执行出现的结果可能会不一样
问题一、什么时候累加结束?
问题二、协程A累加后的s值会覆盖协程B累加后的s值吗?
如何解决?

  1. 全局变量的互斥锁
  2. 使用管道 channel 来解决
2、全局变量的互斥锁

对s进行加锁,并加入n告诉程序什么时候累加结束。

var (
	s = 0
	n = 0
	lock sync.Mutex
)

func sum(a int){
	lock.Lock()
	defer lock.Unlock()
	s+=a
	n++

}
func main() {
	for i:=0;i<100;i++{
		go sum(i)
	}
	for{
		if n == 100{
			break
		}
	}
	fmt.Println(s)
}

似乎这个已经完美解决了所有问题。但是我们使用线程的目的是什么?效率

  1. 加锁了就是要等依次执行,协程A执行完成加锁的代码才能让出资源供协程B执行
  2. 通过全局变量加锁同步来实现通讯,也并不利用多个协程对全局变量的读写操作。

这里就需要使用channel了

3、channel 的基本介绍

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang中的并发编程使用goroutinechannel实现。Goroutine是一种轻量级的线程,可以在同一进程内并发地运行多个任务,而不会造成线程上下文切换的开销。Channel是一种特殊的数据类型,用于在不同的goroutine之间传递数据。 使用goroutine非常简单,只需要在函数调用前加上关键字go即可启动一个goroutine。例如: ``` func main() { go func() { // 这里是一个新的goroutine }() // 这里是主goroutine } ``` 使用channel也很简单,可以使用make函数创建一个channel,然后使用<-操作符发送或接收数据。例如: ``` ch := make(chan int) go func() { ch <- 42 // 发送数据 }() x := <-ch // 接收数据 ``` 在Golang中,channel的发送和接收操作是阻塞的。当发送者向一个已满的channel发送数据时,发送操作会被阻塞,直到有接收者从该channel中接收数据。同样地,当接收者从一个空的channel中接收数据时,接收操作也会被阻塞,直到有发送者向该channel中发送数据。 除了基本的发送和接收操作外,channel还支持以下操作: - 关闭通道:使用close函数关闭通道。关闭通道后,无法再发送数据,但可以继续接收数据。 - 判断通道是否已关闭:使用_, ok := <-ch语句判断通道是否已关闭。 - 使用带缓冲的通道:使用make函数创建一个带缓冲的通道,例如ch := make(chan int, 10)。带缓冲的通道可以存储一定数量的数据,当缓冲区已满时,发送操作会阻塞,直到有接收者从该通道中接收数据。 通过goroutinechannel的组合,Golang实现了高效的并发编程,这也是Golang的一大特色。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值