Go语言进阶之并发编程 | 青训营笔记

简介: Go语言进阶之并发编程 | 青训营笔记

前言

记录加入青训营的每一天的日笔记

并发编程

并发与并行的区别

并发:多线程程序在一个核的CPU上运行

并行:多线程程序在多个核的CPU上运行

Go可以充分发挥多核优势 高效运行

image.png

协程Goroutine

协程:用户态,轻量级线程 栈MB级别

线程:内核态,线程跑多个协程,栈KB级别

image.png

线程的创建、切换、停止较大地占用系统资源

协程的创建和调度由Go语言进行完成

通过开启协程快速打印hello goroutine案例:

package concurrence
import (
    "fmt"
    "time"
)
func hello(i int) {
    println("hello goroutine : " + fmt.Sprint(i))
}
func HelloGoRoutine() {
    for i := 0; i < 5; i++ {
        // go关键字作为创建协程的关键字
        go func(j int) {
            hello(j)
        }(i)
    }
    // 保证子协程运行完前主线程不退出
    time.Sleep(time.Second)
}

CSP(communicating sequential processes)并发模型

不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存”。

Do not communicate by sharing memory; instead, share memory by communicating. “不要以共享内存的方式来通信,相反,要通过通信来共享内存。”

Channel 缓冲通道

创建方式:

make(chan 元素类型, [缓冲大小])

通道是用来传递数据的一个数据结构,可以用于两个goroutine之间,通过传递一个指定类型的值来同步运行和通讯。

操作符<-用于指定通道的方向,实现发送or接收

若未指定方向,则为双向通道

  • 无缓冲通道 make(chan int)
  • 有缓冲通道 make(chan int, 2)

image.png

通过两个Channel通道完成数字平方任务案例:

package concurrence
func CalSquare() {
    src := make(chan int)
    dest := make(chan int, 3)
    go func() {
        defer close(src)
        for i := 0; i < 10; i++ {
            src <- i
        }
    }()
    go func() {
        defer close(dest)
        for i := range src {
            dest <- i * i
        }
    }()
    for i := range dest {
        //复杂操作
        println(i)
    }
}

注意:

  • 如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。
  • 上述代码中之所以能够顺利从通道接收到数据,是因为每次遍历之前都通过关闭对应的通道后再进行的遍历接受数据

并发安全Lock

若采用共享内存实现通信,则会出现多个Goroutine同时操作一块内存资源的情况,这种情况会发生竞态问题(数据竞态)

Mutex互斥锁解决数据竞争

互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有一个goroutine可以访问共享资源。Go语言中使用sync包的Mutex类型来实现互斥锁。


package concurrence
import (
    "sync"
    "time"
)
var (
    x    int64
    lock sync.Mutex
)
func addWithLock() {
    for i := 0; i < 2000; i++ {
        lock.Lock()
        x += 1
        lock.Unlock()
    }
}
func addWithoutLock() {
    for i := 0; i < 2000; i++ {
        x += 1
    }
}
func Add() {
    x = 0
    for i := 0; i < 5; i++ {
        go addWithoutLock()
    }
    time.Sleep(time.Second)
    println("WithoutLock:", x)
    x = 0
    for i := 0; i < 5; i++ {
        go addWithLock()
    }
    time.Sleep(time.Second)
    println("WithLock:", x)
}
func ManyGoWait() {
    var wg sync.WaitGroup
    wg.Add(5)
    for i := 0; i < 5; i++ {
        go func(j int) {
            defer wg.Done()
            hello(j)
        }(i)
    }
    wg.Wait()
}

使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待锁;

当互斥锁释放后,等待的goroutine才可以获取锁进入临界区,多个goroutine同时等待一个锁时,唤醒的策略是随机的。

WaitGroup解决数据竞争

Go语言中除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步,等待组可以保证在并发环境中完成指定数量的任务 WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。


package concurrence
import (
    "fmt"
    "sync"
)
func HelloPrint(i int) {
    fmt.Println("Hello WaitGroup :", i)
}
func ManyGoWait() {
    var wg sync.WaitGroup
    wg.Add(5)
    for i := 0; i < 5; i++ {
        go func(j int) {
            defer wg.Done()
            HelloPrint(j)
        }(i)
    }
    wg.Wait()
}
func main() {
    ManyGoWait()
}

小结

今天学习到的内容还需要进一步的消化,我也是打算将并发编程这一块的内容熟悉透彻了再进行下一部分的课程学习。如果笔记中有错误的地方也希望掘友们可以及时的提出纠正。


目录
相关文章
|
14天前
|
Go
go语言中的数据类型
go语言中的数据类型
11 0
|
19天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
19天前
|
安全 Go
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
|
19天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
20天前
|
Go
使用Go语言发邮件
使用Go语言发邮件
20 2
|
1月前
|
缓存 安全 Java
Go语言小细节
Go语言小细节
36 0
|
19天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
3天前
|
API Go
使用Go语言通过API获取代理IP并使用获取到的代理IP
使用Go语言通过API获取代理IP并使用获取到的代理IP
|
4天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)

热门文章

最新文章

相关实验场景

更多