Go语言学习笔记-第8章 并发

在最开始,首先讲一下 线程,协程,进程的区别和联系。

http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html

单个CPU一次只能运行一个任务

进程:process,是程序的一次执行,每个进程都有独立的内存空间

线程:thread,是轻量级别线程,一个进程可以由多个线程组成,线程是CPU调度的基本单位。线程之间可以共享内存空间。线程之间因为共享内存会实施“锁”机制,有“互斥锁”(Mutual exclusion,Mutex),防止多个线程同时读写某一块内存区域(一次只能一个线程读写一个内存区域)。还有“信号量”(Semaphore),用来保证多个线程不会互相冲突(也就是允许指定个线程访问某一个内存空间)。

协程:也叫微线程,coroutine,是人工可控的,可以在调用中中断然后执行其他的调用。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。内部可以通过yield实现跳转。

子程序:也叫函数

关于内存空间:进程的内存空间是独立的,但是线程之间的空间是可以共享的。进程的内存空间的独立是通过操作系统和硬件MMU协作映射到不同的物理地址上的,所以它们是相互独立的。进程的物理地址一般是不可以跨进程访问的。

一个进程的所有线程是同时执行的。

对于单核CPU,一次只允许一个线程执行。多少核,就是允许多个个线程同时运行

操作系统的设计,因此可以归结为三点:

(1)以多进程形式,允许多个任务同时运行;

(2)以多线程形式,允许单个任务分成不同的部分运行;

(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

调度器:“scheduler”,它关心的只是怎样把单个cpu的运行拆分成一段一段的“运行片”,轮流分给不同的程序去使用,而在宏观上,因为分配切换的速度极快,就制造出多程序并行在一个cpu上的假象。

8.1 并发的含义

并发:逻辑上具备同时处理多个任务的能力

并行:物理上在同一时刻处理多个任务的能力。并行是并发的理想状态,并行的前提条件是多线程或多进程。

用多线程实现分布式和负载平衡,减轻单进程垃圾回收压力;多线程(LWP)抢夺更多的处理器资源。协程提高处理器时间片效率。

go中可以使用go 创建一个并发任务单元

Xnip2022-03-27_10-43-04.jpg

int的default值为0

这里的go func(x,y int)启动了一个并发执行单元,当a:=100执行结束的时候,执行到go func了,a用的是值传递,相当于go func里的a是个局部变量,这个时候回记录下a和counter()的值,注意这个时候counter()执行完毕c变成1了,然后睡一秒,再执行。在开始睡的时候,main继续向下执行,因为进程退出的时候不会等到并发任务结束,所以需要强制然后睡3秒,在醒来之前可以充分保障go func已经结束了。最后结果是 Xnip2022-03-27_10-44-36.jpg

注意这里居然可以直接写println…,当然直接写fmt.Println也是可以的

8.1.1 Wait

默认只有有限个线程可以同时运行,这些线程的个数和处理器核数相等。可以通过runtime.GOMAXPROCS进行设置,也可以通过环境变量修改。

runtime.NumCPu可以返回机器的核数


Go语言学习笔记-第8章 并发
https://nrbackback.github.io/2020/12/07/Go语言学习笔记-第8章 并发/
作者
John Doe
发布于
2020年12月7日
许可协议