这篇文章主要讲解了“go语言中的协程实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“go语言中的协程实例分析”吧!1.该任务的业务代码主动要求切换,即主动让出执行权限2.发生了IO,导致执行阻塞(使用channel让协程阻塞)C#、java中我们执行多个线程,是通过时间片切换来进行的,要知道进行切换,程序需要保存上下文等信息,是比较消耗性能的GO语言中的协程,没有上面这种切换,一定是通过协程主动放出权限,不是被动的。例如:C# 中创建两个线程可以看到1和2是交替执行的Go语言中用协程实现一下runtime.GOMAXPROCS(1)
这个结果就是 执行了1 在执行2上述两种方式来进行协程的切换1.该任务的业务代码主动要求切换,即主动让出执行权限2.通过channel进行阻塞执行的结果一样后面又继续执行1了运行结果Start Goroutines等待执行结束333333333311111111112222222222(1)runtime.GOMAXPROCS(1) 的作用是什么?runtime包的GOMAXPROCS 函数。这个函数允许程序更改调度器可以使用的逻辑处理器的数量。如果不想在代码里做这个调用,也可以通过修改和这个函数名字一样的环境变量的值来更改逻辑处理器的数量。(2)为什么先输出3后输出1和2?调度器源码中有体现: 有一个队列,还有一个优先执行——即最后一个, 在只有一个逻辑处理器的情况下,先执行优先的那个,再顺序执行队列中的。不过经过各种实验发现这个执行顺序其实是变的,貌似纠结这个顺序也没有什么意思。(3)WaitGroup 是什么意思?WaitGroup 是一个计数信号量,可以用来记录并维护运行的goroutine。如果WaitGroup的值大于0,Wait 方法就会阻塞。为了减小WaitGroup 的值并最终释放main 函数,使用defer 声明在函数退出时调用Done 方法。(defe免费云主机域名r 有点像C#当中的fianlly)补充:调度算法中,如果多个goroutine中某个执行过长,此时会将其停止让给其他goroutine继续执行,待到其他都执行完成,在将其进行执行。如下图:G4和G5就进行了切换如下代码可以验证上面的问题:printPrime 这个函数作用是查找显示 5000 以内的素数值,这是一个比较耗时的程序。运行结果:数字比较多,不打印了,但是可以看到结果是A和B两个协程之间的切换。上面的代码都是设置GOMAXPROCS为1的情况,给每个可用的核心分配一个逻辑处理器runtime.GOMAXPROCS(runtime.NumCPU())
这样运行第一个程序的结果如下Start Goroutines
等待执行结束133333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333332111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222可以看到1、2、3没有什么规律。什么竞争状态:如果两个或者多个goroutine 在没有互相同步的情况下,访问某个共享的资源,并试图同时读和写这个资源,就处于相互竞争的状态,这种情况被称作竞争状态(race candition)竞争状态是比较容易出现问题的地方,所以对一个共享资源的读和写操作必须是原子化的,换句话说,同一时刻只能有一个goroutine 对共享资源进行读和写操作。运行结果:Final Counter: 2变量 counter 会进行4 次读和写操作,每个goroutine 执行两次。但是,程序终止时,counter变量的值为2,这是因为两个协程之间产生了竞争,对同一个counter进行读写,下面这个图很好的诠释了为什么最后counter是2补充:runtime.Gosched()用于让出CPU时间片。一种修正代码、消除竞争状态的办法是,使用Go 语言提供的锁机制,来锁住共享资源,从而保证goroutine 的同步状态。Go 语言提供了传统的同步goroutine 的机制,就是对共享资源加锁。使用atomic包来提供对数值类型的安全访问。运行结果Final Counter: 4atmoic 包的AddInt64 函数。这个函数会同步整型值的加法,方法是强制同一时刻只能有一个goroutine 运行并完成这个加法操作。当goroutine 试图去调用任何原子函数时,这些goroutine 都会自动根据所引用的变量做同步处理。另外两个有用的原子函数是LoadInt64 和StoreInt64。这两个函数提供了一种安全地读和写一个整型值的方式。主协程main函数执行了1秒,然后将shutdown中的值设置为1,A和B的协程中通过读取shutdown是否等于1来判断是否结束协程。运行结果:Doing A Work
Doing B Work
Doing A Work
Doing B Work
Doing A Work
Doing B Work
Doing A Work
Doing B Work
Shutdown Now
Shutting A Down
Shutting B Down2、互斥锁另一种同步访问共享资源的方式是使用互斥锁(mutex)。互斥锁这个名字来自互斥(mutualexclusion)的概念。互斥锁用于在代码上创建一个临界区,保证同一时间只有一个goroutine 可以执行这个临界区代码运行结果:Final Counter: 6如上面的代码,最终的结果还是6.mutex.lock he mutex.Unlock之间的代码,同一时刻只允许一个goroutine进入,所以保证数据的正确性。补充对于 runtime.Gosched()的理解,有两个问题 1. 当执行了这句话,貌似让出了执行,那么它后面的语句还能执行么感谢各位的阅读,以上就是“go语言中的协程实例分析”的内容了,经过本文的学习后,相信大家对go语言中的协程实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是百云主机,小编将为大家推送更多相关知识点的文章,欢迎关注!
本篇内容主要讲解“C语言中的程序环境与预处理实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言中的程序环境与预处理实例分析”吧!在AN免费云主机域名SI C的任何一种实现中,存在两个不同的环境第1种是翻译…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。