分析Go语言中CSP并发模型与Goroutine的基本使用

 更新时间:2021年06月16日 09:07:53   作者:TechFlow2019  
我们都知道并发是提升资源利用率最基础的手段,尤其是当今大数据时代,流量对于一家互联网企业的重要性不言而喻。串流显然是不行的,尤其是对于web后端这种流量的直接载体。并发是一定的,问题在于怎么执行并发。常见的并发方式有三种,分别是多进程、多线程和协程

一、并发实现模型

1.1、多进程

在之前的文章当中我们曾经介绍过,进程是操作系统资源分配的最小单元。所以多进程是在操作系统层面的并发模型,因为所有的进程都是有操作系统的内核管理的。所以每个进程之间是独立的,每一个进程都会有自己单独的内存空间以及上下文信息,一个进程挂了不会影响其他进程的运行。这个也是多进程最大的优点,但是它的缺点也很明显。

最大的缺点就是开销很大,创建、销毁进程的开销是最高的,远远高于创建、销毁线程。并且由于进程之间互相独立,导致进程之间通信也是一个比较棘手的问题,进程之间共享内存也非常不方便。因为这些弊端使得在大多数场景当中使用多进程都不是一个很好的做法。

1.2、多线程

多线程是目前最流行的并发场景的解决方案,由于线程更加轻量级,创建和销毁的成本都很低。并且线程之间通信以及共享内存非常方便,和多进程相比开销要小得多。

但是多线程也有缺点,一个缺点也是开销。虽然线程的开销要比进程小得多,但是如果创建和销毁频繁的话仍然是不小的负担。针对这个问题诞生了线程池这种设计。创建一大批线程放入线程池当中,需要用的时候拿出来使用,用完了再放回,回收和领用代替了创建和销毁两个操作,大大提升了性能。另外一个问题是资源的共享,由于线程之间资源共享更加频繁,所以在一些场景当中我们需要加上锁等设计,避免并发带来的数据紊乱。以及需要避免死锁等问题。

1.3、协程

也叫做轻量级线程,本质上仍然是线程。相比于多线程和多进程来说,协程要小众得多,相信很多同学可能都没有听说过。和多线程最大的区别在于,协程的调度不是基于操作系统的而是基于程序的。

也就是说协程更像是程序里的函数,但是在执行的过程当中可以随时挂起、随时继续。

我们举个例子,比如这里有两个函数:

def A():
    print '1'
    print '2'
    print '3'

def B():
    print 'x'
    print 'y'
    print 'z'

如果我们在一个线程内执行A和B这两个函数,要么先执行A再执行B要么先执行B再执行A。输出的结果是确定的,但如果我们用写成来执行A和B,有可能A函数执行了一半刚输出了一条语句的时候就转而去执行B,B输出了一条又再回到A继续执行。不管执行的过程当中发生了几次中断和继续,在操作系统当中执行的线程都没有发生变化。也就是说这是程序级的调度。

那么和多线程相比,我们创建、销毁线程的开销就完全没有了,整个过程变得非常灵活。但是缺点是由于是程序级别的调度,所以需要编程语言自身的支持,如果语言本身不支持,就很难使用了。目前原生就支持协程的语言并不多,显然golang就是其中一个。

二、共享内存与CSP

我们常见的多线程模型一般是通过共享内存实现的,但是共享内存就会有很多问题。比如资源抢占的问题、一致性问题等等。为了解决这些问题,我们需要引入多线程锁、原子操作等等限制来保证程序执行结果的正确性。

除了共享内存模型之外,还有一个经典模型就是CSP模型。CSP模型其实并不新,发表已经好几十年了。CSP的英文全称是Communicating Sequential Processes,翻译过来的意思是通信顺序进程。CSP描述了并发系统中的互动模式,是一种面向并发的语言的源头。

Golang只使用了CSP当中关于Process/Channel的部分。简单来说Process映射Goroutine,Channel映射Channel。Goroutine即Golang当中的协程,Goroutine之间没有任何耦合,可以完全并发执行。Channel用于给Goroutine传递消息,保持数据同步。虽然Goroutine之间没有耦合,但是它们与Channel依然存在耦合。

整个Goroutine和Channel的结构有些类似于生产消费者模式,多个线程之间通过队列共享数据,从而保持线程之间独立。这里不过多深入,我们大概有一个印象即可。

三、Goroutine

Goroutine即golang当中的协程,这也是golang这门语言的核心精髓所在。正是因为Goroutine,所以golang才叫做golang,所以人们才选择golang。

相比于Java、Python等多线程的复杂的使用体验而言,golang当中的Goroutine的使用非常简单,简单到爆表。只需要一个关键字就够了,那就是go。所以你们应该明白为什么golang叫做Go语言不叫别的名字了吧?

比如我们有一个函数:

func Add(x, y int) int{
    z := x + y
    fmt.Println(z)
}

我们希望启动一个goroutine去执行它, 应该怎么办?很简单,只需要一行代码:

go Add(3, 4)

我们还可以用go关键字来使用goroutine来执行一个匿名函数:

go func(x, y int) {
    fmt.Println(x + y)
}(3, 4)

需要注意的是,当我们使用go关键字的时候,是不能获取返回值的。也就是说z := go Add(3, 4)是违法的。乍看起来似乎不合理,但是道理其实是很简单的。如果我们希望一个变量承接一个函数的返回值,说明这里的逻辑是串行的,那么我们使用goroutine的意义是什么?所以这里看似不合理,其实是设计者下了心思的。

以上就是分析Go语言中CSP并发模型与Goroutine的基本使用的详细内容,更多关于Go CSP并发模型 Goroutine的资料请关注脚本之家其它相关文章!

相关文章

  • 深入理解Go语言实现多态 

    深入理解Go语言实现多态 

    本文主要介绍了Go语言实现多态,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • golang中bufio.SplitFunc的深入理解

    golang中bufio.SplitFunc的深入理解

    这篇文章主要给大家介绍了关于golang中bufio.SplitFunc的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • 深入理解Golang中指针的用途与技巧

    深入理解Golang中指针的用途与技巧

    在 Go 语言中,指针是一种重要的概念,了解和正确使用指非常关键,因此本文小编就来和大家讲讲Golang 中指针的概念与用法,希望对大家有所帮助
    2023-05-05
  • golang中net的tcp服务使用

    golang中net的tcp服务使用

    这篇文章主要介绍了golang中net的tcp服务使用,文章通过服务端监听端口 展开主题的详细内容,具有一定的参考价值,需要的 小伙伴可以参考一下
    2022-04-04
  • Go语言CSP并发模型实现MPG

    Go语言CSP并发模型实现MPG

    这篇文章主要为大家介绍了Go语言CSP并发模型实现MPG图文详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Golang设计模式中抽象工厂模式详细讲解

    Golang设计模式中抽象工厂模式详细讲解

    抽象工厂模式用于生成产品族的工厂,所生成的对象是有关联的。如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。比如本例子中使用RDB和XML存储订单信息,抽象工厂分别能生成相关的主订单信息和订单详情信息
    2023-01-01
  • vscode配置go开发环境的实战过程

    vscode配置go开发环境的实战过程

    vscode配置go的开发环境很简单,下面这篇文章主要给大家介绍了关于vscode配置go开发环境的实战过程,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)

    Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)

    这篇文章给大家介绍了Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱),需求很简单,就是用户输入自己的邮箱后,使用官方邮箱给用户发送替邮件模版,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-10-10
  • 使用Go构建一款静态分析工具Owl详解

    使用Go构建一款静态分析工具Owl详解

    Owl是一款开源项目依赖分析工具,可以快速在指定的项目目录下查找符合某些特征的源代码文件或者依赖文件,这篇文章主要介绍了使用Go构建一款静态分析工具,需要的朋友可以参考下
    2022-06-06
  • Go1.18都出泛型了速来围观

    Go1.18都出泛型了速来围观

    泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型,本文通过例子给大家介绍下如何使用泛型,对Go1.18泛型相关知识感兴趣的朋友一起看看吧
    2022-03-03

最新评论