golang协程

最近在使用golang做一个爬虫,涉及到多线程,golang是没有多线程的,但是有一种更轻量级能达到类似多线程的效果,协程,golang原生支持协程。
一、怎么理解协程?
协程是golang语言特性的实现,比线程更低一级的运行方式,它不属于操作系统功能,不由操作系统分配cpu、内存,而是由golang自己实现运行资源的调度使用。也正是因此执行效率要高于线程。但是协程需要主动让出控制权后供其他协程运行。
二、如何创建协程?
这里有2种方式创建:
1、使用go创建

   go sf("a")

2、使用go函数块创建

go func() {
		sf("b")
	}()

三、使用协程的问题
1、主线程执行完成后直接结束了,此时若协程未执行完成,也会直接结束,毫无征兆。
下面是个例子

func main() {
	fmt.Println("开始启动...")
	go sf("a")
	go sf("b")
}

func sf(s string) {
	for i := 0; i < 10; i++ {
		fmt.Println(s+" ->>>", i)
	}
}

运行完成之后根本不会等两个协程完成运行,主函数直接结束了,如果将代码改一下
改版1:

func main() {
	fmt.Println("开始启动...")
	go sf("a")
	go sf("b")
       time.Sleep(time.Duration(2)*time.Minute)
}

在主函数这里阻塞一下,就可以了,但是这种方式在实际开发中是不可行的,大多不能提前知道协程需要多久运行完成。
改版2:

func main() {
	fmt.Println("开始启动...")
	var wg = sync.WaitGroup{}
	wg.Add(2)
	go func() {
		sf("a")
		wg.Done()
	}()
	go func() {
		sf("b")
		wg.Done()
	}()
	wg.Wait()
}

这样运行就ok了,这里使用了golang的WaitGroup。
理解起来就是创建一个等待的组,可以动态的添加组员的数量,然后在主函数最后一行执行wg.Wait() 来阻塞检查组员是否都完成了,协程中调用wg.Done()方法进行减一操作告知当前协程完成。
这样也会带来新的问题:
1、无法精确控制协程
2、无法准确得知哪个协程完成了或未完成
3、代码过于原始(繁琐)

拿java的多线程来理解,这个WaitGroup就像一个线程池,但是池子里只有计数器,没有实际对象。在Wait()方法一直在等待WaitGroup的校验信号,当一个协程完成时使用Done()通知WaitGroup已完成,当所有协程全部通知完成了Wait()释放,这就是一个非常简单的消息模型。
在协程这块,希望golang能优化使用方式,尽可能优雅一些。
找到了一篇讲的挺到位的文章,手动传送门 https://www.cnblogs.com/liang1101/p/7285955.html
欢迎关注我的个人公众号

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章