go并发编程学习 | 青训营笔记

102 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第 4

|| 🎶今日笔记🎶 ||

项目笔记:并发编程

前言

并发并行的区别

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

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

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


协程Goroutine

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

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

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

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

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

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

Channel 通道

创建方式:make(chan 元素类型, [缓冲大小])

通道是用来传递数据的一个数据结构,可以用于两个goroutine之间,通过传递一个指定类型的值来同步运行和通讯。操作符<-用于指定通道的方向,实现发送or接收若未指定方向,则为双向通道
通过两个Channel通道案例:

package concurrence

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

锁 Lock

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

如何解决互斥锁解决数据竞争:

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

package concurrence

import (
    "sync"
    "time"
)

var (
    x int64
    lock sync.Mutex
)

func addWithLock() {
    for i := 0; i < 1000; i++ {
        lock.Lock()
        x += 1
        lock.Unlock()
    }
}
func addWithoutLock() {
    for i := 0; i < 1000; 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 < 7; 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()
}

~ End ~