1

go语言学习之并发并行【字节跳动青训营】

 1 year ago
source link: https://blog.51cto.com/u_15568258/5283312
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Table of Contents

一,并发编程

1.1,并发和并行的区别

并发:
go语言学习之并发并行【字节跳动青训营】_bash
并发,就是通过一种算法将 CPU 资源合理地分配给多个任务,当一个任务执行 I/O 操作时,CPU 可以转而执行其它的任务,等到 I/O 操作完成以后,或者新的任务遇到 I/O 操作时,CPU 再回到原来的任务继续执行。
通过将 CPU 的使用权在恰当的时机分配给不同的任务,使得多个任务在视觉上看起来是一起执行的。CPU 的执行速度极快,多任务切换的时间也极短,用户根本感受不到,所以并发执行看起来才跟真的一样。
总结:
其实并发就是单核cpu不断的切换任务,给我们的感觉像是多个任务同时进行的。

并行:
go语言学习之并发并行【字节跳动青训营】_插入图片_02
多核 CPU 的每个核心都可以独立地执行一个任务,而且多个核心之间不会相互干扰。在不同核心上执行的多个任务,是真正地同时运行,这种状态就叫做并行。
一图来区别它们。
go语言学习之并发并行【字节跳动青训营】_bash_03

1.2,Goroutine

go中使用Goroutine来实现并发concurrently。Go应用程序可以并发运行数千个Goroutines。

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

func main() {
	for i := 0; i < 5; i++ {
		go func(j int) {

			hello(j)
		}(i)
	}
	time.Sleep(time.Second)
}

如上代码开了五个任务并发执行,输出来看一下。
go语言学习之并发并行【字节跳动青训营】_插入图片_04

1.3,channel

Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。
go语言学习之并发并行【字节跳动青训营】_插入图片_05
go语言学习之并发并行【字节跳动青训营】_插入图片_06

package main

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

上述代码解释:
A子协程发生0~9数字到无缓冲通道。
B子协程将传入的数字计算为平方到有缓冲通道。
主协程输出结果如下:
go语言学习之并发并行【字节跳动青训营】_插入图片_07

1.4,并发安全Lock

线程安全是指,函数或者某个函数库在多线程的模式被调用时,能够正确处理多个线程之间共享变量,使得程序可以正常运行。
线程调用时线程之间会随时发生切换会发生不可预料的结果,出现线程不安全。

Lock可以在“关键的位置”提供串行特性,保证数据安全与独立

1.5,WaitGroup

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

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

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(j int) {
			defer wg.Done()
			hello(j)
		}(i)
	}
	wg.Wait()
}

输出来看一下。
go语言学习之并发并行【字节跳动青训营】_i++_09


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK