Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Golang并发详解大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

Go-简洁的并发

多核处理器越来越普及。有没有一种简单的办法,能够让我们写的软件释放多核的威力?是有的。随着Golang,Erlang,Scala等为并发设计的程序语言的兴起,新的并发模式逐渐清晰。正如过程式编程和面向对象一样,一个好的编程模式有一个极其简洁的内核,还有在此之上丰富的外延。可以解决现实世界中各种各样的问题。本文以GO语言为例,解释其中内核、外延。

并发模式之内核

这种并发模式的内核只需要协程通道就够了。协程负责执行代码,通道负责在协程之间传递事件。

不久前,并发编程是个非常困难的事。要想编写一个良好的并发程序,我们不得不了解线程,锁,semaphore,barrier甚至cpu更新高速缓存的方式,而且他们个个都有怪脾气,处处是陷阱。笔者除非万不得以,决不会自己操作这些底层并发元素。一个简洁的并发模式不需要这些复杂的底层元素,协程和通道就够了。

协程是轻量级的线程。在过程式编程中,当调用一个过程的时候,需要等待其执行完才返回。而调用一个协程的时候,不需要等待其执行完,会立即返回。协程十分轻量,Go语言可以在一个进程中执行有数以十万计的协程,依旧保持高性能。而对于普通的平台,一个进程有数千个线程,其cpu会忙于上下文切换,性能急剧下降。随意创建线程可不是一个好主意,但是我们可以大量使用的协程。

通道是协程之间的数据传输通道。通道可以在众多的协程之间传递数据,具体可以值也可以是个引用。通道有两种使用方式。

  • 协程可以试图向通道放入数据,如果通道满了,会挂起协程,直到通道可以为他放入数据为止。
  • 协程可以试图向通道索取数据,如果通道没有数据,会挂起协程,直到通道返回数据为止。

如此,通道就可以在传递数据的同时,控制协程的运行。有点像事件驱动,也有点像阻塞队列。

这两个概念非常的简单,各个语言平台都会有相应的实现。在Java和C上也各有库可以实现两者。

@H_597_40@mailBox
Golang Erlang Scala(Actor)
协程 goroutInes process actor
消息队列 chAnnel chAnnel

只要有协程和通道,就可以优雅的解决并发的问题。不必使用其他和并发有关的概念。那如何用这两把利刃解决各式各样的实际问题呢?

并发模式之外延

协程相较于线程,可以大量创建。打开这扇门,我们拓展出新的用法,可以做生成器,可以让函数返回“服务”,可以让循环并发执行,还能共享变量。但是出现新的用法的同时,也带来了新的棘手问题,协程也会泄漏,不恰当的使用会影响性能。下面会逐一介绍各种用法和问题。演示的代码用GO语言写成,因为其简洁明了,而且支持全部功能

生成

有的时候,我们需要有一个函数能不断生成数据。比方说这个函数可以读文件,读网络,生成自增长序列,生成随机数。这些行为的特点就是,函数的已知一些变量,如文件路径。然后不断调用,返回新的数据。

下面生成随机数为例, 以让我们做一个会并发执行的随机生成器。

非并发的做法是这样的

上面是一个函数,返回一个int。假如rand.Int()这个函数调用需要很长时间等待,那该函数调用者也会因此而挂起。所以我们可以创建一个协程,专门执行rand.Int()。

上面的这段函数就可以并发执行了rand.Int()。有一点值得注意到函数的返回可以理解为一个“服务”。但我们需要获取随机数据 时候,可以随时向这个服务取用,他已经为我们准备好了相应的数据,无需等待,随要随到。如果我们调用这个服务不是很频繁,一个协程足够满足我们的需求了。但如果我们需要大量访问,怎么办?我们可以用下面介绍的多路复用技术,启动若干生成器,再将其整合成一个大的服务。

调用生成器,可以返回一个“服务”。可以用在持续获取数据的场合。用途很广泛,读取数据,生成ID,甚至定时器。这是一种非常简洁的思路,将程序并发化。

多路复用

多路复用是让一次处理多个队列的技术。Apache使用处理每个连接都需要一个进程,所以其并发性能不是很好。而Nighx使用多路复用的技术,让一个进程处理多个连接,所以并发性能比较好。同样,在协程的场合,多路复用也是需要的,但又有所不同。多路复用可以将若干个相似的小服务整合成一个大服务。

那么让我们用多路复用技术做一个更高并发的随机生成器吧。

上面是使用了多路复用技术的高并发版的随机生成器。通过整合两个随机生成器,这个版本的能力是刚才的两倍。然协程可以大量创建,但是众多协程还是会争抢输出的通道。Go语言提供了SELEct关键字来解决,各家也有各家窍门。加大输出通道的缓冲大小是个通用的解决方法

多路复用技术可以用来整合多个通道。提升性能和操作的便捷。配合其他的模式使用有很大的威力。

Furture技术

Furture是一个很有用的技术,我们常常使用Furture来操作线程。我们可以在使用线程的时候,可以创建一个线程,返回Furture,之后可以通过它等待结果。 但是在协程环境下的Furtue可以更加彻底,输入参数同样可以是Furture的。

调用一个函数的时候,往往是参数已经准备好了。调用协程的时候也同样如此。但是如果我们将传入的参数设为通道,这样我们就可以在不准备好参数的情况下调用函数。这样的设计可以提供很大的自由度和并发度。函数调用函数参数准备这两个过程可以完全解耦。下面举一个用该技术访问数据库的例子。

//一个查询结构体
type query struct {
//参数ChAnnel
//结果ChAnnel
@H_502_686@result String
}
@H_386_673@ //执行Query
exeCQuery ( q query {
//启动协程
{
//获取输入
sql - q . sql
//访问数据库输出结果通道
. result "get " + sql
)
}
{
//初始化Query
q =
query { String 1 ) }
//执行Query,注意执行的时候无需准备参数
@H_197_773@( q )
//准备参数
. sql "SELEct * FROM table"
//获取结果
Println ( . result )
}

大佬总结

以上是大佬教程为你收集整理的Golang并发详解全部内容,希望文章能够帮你解决Golang并发详解所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
猜你在找的Go相关文章