脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - 分析Go语言中CSP并发模型与Goroutine的基本使用

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

2021-08-09 01:23TechFlow2019 Golang

我们都知道并发是提升资源利用率最基础的手段,尤其是当今大数据时代,流量对于一家互联网企业的重要性不言而喻。串流显然是不行的,尤其是对于web后端这种流量的直接载体。并发是一定的,问题在于怎么执行并发。常见的

一、并发实现模型

1.1、多进程

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

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

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

1.2、多线程

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

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

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

1.3、协程

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

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

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

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

  1. def A():
  2. print '1'
  3. print '2'
  4. print '3'
  5.  
  6. def B():
  7. print 'x'
  8. print 'y'
  9. 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依然存在耦合。

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

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

三、Goroutine

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

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

比如我们有一个函数:

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

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

  1. go Add(3, 4)

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

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

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

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

原文链接:https://www.cnblogs.com/techflow/p/13534288.html

延伸 · 阅读

精彩推荐
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02