Go语言进阶(并发线程)| 青训营

55 阅读1分钟

一、语言进阶(并发编程)

image.png 并发:如图左,多个线程程序在一个核的CPU上执行
并行:如图右,多个线程程序在多个核的CPU上执行

1. Goroutine

image.png 协程:用户态,轻量级线程,栈KB级别。
线程:内核态,线程跑多个协程,栈MB级别。
例子:打印hello goroutine

package main

import (
	"fmt"
	"time"
)

func hello(i int) {
	println("hello goroutine : " + fmt.Sprint(i))
}

func HelloGoRoutine() {
	for i := 0; i < 5; i++ {
		go func(j int) {
			hello(j)
		}(i)
	}
	time.Sleep(time.Second)
}

func main() {
	HelloGoRoutine()
}

运行结果:

image.png

2. CSP (Communicating Sequential Processes)

image.png

3. Channel

image.png
例子(通过通讯来共享内存):

image.png

package main

func CalSquare() {
	src := make(chan int)
	dest := make(chan int, 3)
	// 运行A协程
	go func() {
		defer close(src)
		for i := 0; i < 10; i++ {
			src <- i
		}
	}()

	// 运行B协程
	go func() {
		defer close(dest)
		for i := range src {
			dest <- i * i
		}

	}()

	// 主线程
	for i := range dest {
		println(i)
	}
}

func main() {
	CalSquare()
}

4. 并发安全(Lock)

例子:通过共享内存通信

package main

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 main() {
	Add()
}

运行结果,通过多次运行,不加锁的情况可能会导致结果不符合预期:

image.png

1.5 WaitGroup

image.png 例子:

package main

import (
	"fmt"
	"sync"
)

func hello(i int) {
	println("hello goroutine : " + fmt.Sprint(i))
}

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()
}

func main() {
	ManyGoWait()
}