美文网首页工作生活
15.手撕Go语言-并发编程

15.手撕Go语言-并发编程

作者: imsilence | 来源:发表于2019-06-30 19:51 被阅读0次

并发编程开发将一个过程按照并行算法拆分为多个可以独立执行的代码块,从而充分利用多核和多处理器提高系统吞吐率

顺序、并发与并行

  1. 顺序是指发起执行的程序只能有一个

  2. 并发是指同时发起执行(同时处理)的程序可以有多个(单车道并排只能有一辆车,可同时驶入路段多辆车)

  3. 并行是指同时执行(同时做)的程序可以有多个 (多车道并排可以有多个车)

例程(Goroutine)

Go语言中每个并发执行的单元叫Goroutine,使用go关键字后接函数调用来创建一个Goroutine

15.01.png

main函数也是由一个例程来启动执行,这个例程称为主例程,其他例程叫工作例程。主例程结束后工作例程也会随之销毁,使用sync.WaitGroup(计数信号量)来维护执行例程执行状态

15.02.png

可以通过runtime包中的GoSched让例程主动让出CPU,也可以通过time.Sleep让例程休眠从而让出CPU

闭包陷阱

15.03.png

因为闭包使用函数外变量,当例程执行是,外部变量已经发生变化,导致打印内容不正确,可使用在创建例程时通过函数传递参数(值拷贝)方式避免

并发程序通信方式

共享数据(同步)

多个并发程序需要对同一个资源进行访问,则需要先申请资源的访问权限,同时再使用完成后释放资源的访问权。当资源被其他程序已申请访问权后,程序应该等待访问权被释放并被申请到时进行访问操作。同一时间资源只能被一个程序访问和操作

管道(异步)

数据处理者处理完数据后将数据放入缓冲区中,数据接收者从缓冲区中获取数据,处理者不用等待接收者是否准备好处理数据

共享数据

15.04.png

多个例程对同一个内存资源进行修改,未对资源进行同步限制,导致修改数据混乱

互斥锁

Go语言中sync包中提供了Mutex(互斥锁),可以用于对资源加锁和释放锁提供对资源同步方式访问

15.05.png

原子操作

原子操作是指过程不能中断的操作s,go语言sync/atomic包中提供提供了五类原子操作函数,其操作对象为整数型或整数指针

  1. Add*:增加/减少
  2. Load*:载入
  3. Store*:存储
  4. Swap*:更新
  5. CompareAndSwap*:比较第一个参数引用指是否与第二个参数值相同,若相同则将第一个参数值更新为第三个参数
15.06.png

管道

在go语言中可以通过chan来定义管道,可以通过操作符<-和->对管道进行读取和写入操作

通过管道维护例程状态

15.07.png

声明

管道是声明需要指定管道存放数据的类型,管道原则可以存放任何类型,但只建议用于存放值类型或者只包含值类型的结构体。在管道声明后,会被初始化为nil

15.08.png

初始化

使用make函数初始化,make(chan type)/make(chan type, len),不带len参数的用于创建无缓存区的管道,使用len创建指定缓冲区长度的管道

15.09.png

读取和写入

可通过操作符<-和->对管道进行读取和写入操作,当写入无缓冲区管道或由缓冲区管道已满时写入则会阻塞直到管道中元素被其他例程读取。同理,当管道中无元素时读取时也会阻塞到管道被其他例程写入元素

15.10.png

关闭管道

可通过close函数关闭管道,关闭后的管道不能被写入,当读取到最后一个元素后可通过读取的第二个参数用于判断是否结束

15.11.png

for-range遍历管道

管道也可以通过for-range进行遍历

15.12.png

只读和只写管道

可以在函数参数时声明管道为chan<-或chan->,表示管道只写或只读

15.13.png

select-case语句

当写入无缓冲区管道或由缓冲区管道已满时写入则会阻塞直到管道中元素被其他例程读取。同理,当管道中无元素时读取时也会阻塞到管道被其他例程写入元素,若需要同时对多个管道进行监听(写入或读取),则可以使用select-case语句

15.14.png

select语句自上到下执行case语句中对管道的读取和写入,当操作成功则执行对应子语句,否则执行下一个case语句,当所有case都失败,则执行default语句,default语句可省略

超时机制

可以通过select-case实现对执行操作超时的控制

15.15.png

Select-case语句监听每个case语句中管道的读取,当某个case语句中管道读取成功则执行对应子语句

Go语言time包实现了After函数,可以用于实现超时机制,After函数返回一个只读管道

15.16.png

sync包

sync包提供了同步原语,常用结构体有:

  • sync.Mutex:互斥锁

  • sync.RWMutex:读写锁

  • sync.Cond:条件等待

  • sync.Once:单次执行

    15.17.png
  • sync.Map:例程安全映射

  • sync.Pool:对象池

  • sync.WaitGroup:组等待

runtime包

runtime包提供了与Go运行时系统交互的操作,常用函数:

  • runtime.Gosched(): 当前goroutine让出时间片
  • runtime.GOROOT(): 获取Go安装路径
  • runtime.NumCPU(): 获取可使用的逻辑CPU数量
  • runtime.GOMAXPROCS(1):设置当前进程可使用的逻辑CPU数量
  • runtime.NumGoroutine(): 获取当前进程中goroutine的数量
15.18.png

相关文章

  • 15.手撕Go语言-并发编程

    并发编程开发将一个过程按照并行算法拆分为多个可以独立执行的代码块,从而充分利用多核和多处理器提高系统吞吐率 顺序、...

  • Go基础语法(九)

    Go语言并发 Go 是并发式语言,而不是并行式语言。 并发是指立即处理多个任务的能力。 Go 编程语言原生支持并发...

  • Go并发

    Go语言中的并发编程 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很...

  • Go语言简介

    Go语言简介 Go语言设计的初衷 针对其他语言的痛点进行设计并加入并发编程为大数据,微服务,并发而生的通用编程语言...

  • 16.并发

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因。 Go语言...

  • Go语言基础之并发

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因。 Go语言...

  • Go 的并发性与调度器

    本篇文章是我对 Go 语言并发性的理解总结,适合初步了解并发,对 Go 语言的并发编程与调度器原理有兴趣的读者。 ...

  • go语言开发培训班哪里好

    Go作为专门为并发和大数据设计的语言,在编程界占据越来越重要的地位!越来越多的人开始学习go编程语言,go语言开发...

  • 十分钟读懂:Java并发——CSP模型

    Go Go是一门号称从语言层面支持并发的编程语言,支持并发也是Go非常重要的特性之一 Go支持协程,协程可以类比J...

  • Go语言的优缺点及其扫盲

    1. go语言介绍 1.1.语言为并发而生 go语言(或 Golang)是Google开发的开源编程语言,诞生于2...

网友评论

    本文标题:15.手撕Go语言-并发编程

    本文链接:https://www.haomeiwen.com/subject/mczbcctx.html