Golang并发编程入门教程
时间单位
- 1S = 1000ms
- 1ms = 1000us
- 1us = 1000ns
并发与并行
- 并行: 借助多核 cpu 实现。 (真 并行)
- 并发:
- 宏观:用户体验上,程序在并行执行。
- 微观:多个计划任务,顺序执行。在飞快的切换。轮换使用 cpu 时间轮片。 【假 并行】
进程并发
- 程序:编译成功得到的二进制文件。
- 占用磁盘空间
- 死的
- 系统中相同的程序一般只有一个,有可能存在不同版本号的程序
- 进程:运行起来程序。 占用系统资源。
- 进程是根据程序创建的,运行在内存中
- 活的
- 一个程序可以启动N个进程
- 一个程序可以启动N个进程,程序和进程的关系是1对N的关系。
进程状态
- 初始态
- 就绪态:程序会经常从就绪态切换到运行态。
- 运行态:只有运行态能切换到阻塞态。
- 挂起(阻塞)态:阻塞态可以切换回运行态继续往下执行。
- 终止(停止)态
线程并发
- 线程:LWP 轻量级的 进程。最小的执行单位。是cpu分配时间轮片的对象。
- 进程: 最小的系统资源分配单位。
同步
- 协同步调。规划先后顺序。
- 线程同步机制:
- 互斥锁(互斥量):建议锁。拿到锁以后,才能访问数据,没有拿到锁的线程,阻塞等待。等到拿锁的线程释放锁。
- 读写锁:一把锁(读属性、写属性)。 写独占,读共享。 写锁优先级高。
协程并发
- Python、Lua、Rust。。。
- 21世纪
- 线程会io阻塞,协程可以在线程io阻塞期间相互切换,执行其他不需要消耗io操作的协程
- 提高程序执行的效率
总结
- 进程、线程、协程 都可以完成并发。
- 稳定性强、节省资源、效率高。
- 老板——手机:
- 生产线 —— 设备、材料、厂房 —— 进程。(资源分配单位)
- 工人 —— 线程。 —— 单进程、单线程的 程序。
- 50 工人 —— 50 线程。 ——单进程、多线程的 程序。
- 10 条生产线 —— 500 工人 —— 。多进程、多线程的 程序。
- 利用闲暇时间义务搬砖 —— 协程。—— 多进程、多线程、多协程 程序。
创建Goroutine程
- 创建于进程中。 直接使用 go 关键,放置于 函数调用前面,产生一个 go程。 并发。
示例代码:
package mainimport ("fmt"`time`
)// 唱歌
func sing() {for i:=0;i<50;i++ {fmt.Println("----正在唱:隔壁泰山----")}
}// 跳舞
func dance() {for i:=0;i<50;i++ {fmt.Println("----正在跳舞:赵四街舞----")}
}func main() {go sing() // 开启goroutinego dance() // 另一个goroutine,会抢夺CPU执行权,两个goroutine交替执行time.Sleep(time.Second)
}
Goroutine的特性:【重点】
- 主go程结束,子go程随之退出。
示例代码:
package mainimport ("fmt""time"
)func main() {go func() { // 创建一个 子go 程for i := 0; i < 5; i++ {fmt.Println("------I'm goroutine -------")time.Sleep(time.Second)}}()// 主goroutine结束,子goroutine随着退出// 所以,子goroutine很有可能没有执行完就退出了fmt.Println("------I'm main-------")
}
runtime.Gosched()
- 出让当前go程所占用的 cpu时间片。当再次获得cpu时,从出让位置继续回复执行。
- 时间片轮转调度算法。
示例代码:
package mainimport ("fmt""runtime"
)func main() {go func() {for {runtime.Gosched()fmt.Println("goroutine 1执行。。。。")}}()for {runtime.Gosched() // 出让当前 cpu 时间片。fmt.Println("主go程执行。。。。")}
}
runtime.Goexit()
- return: 返回当前函数调用到调用者那里去。 return之前的 defer 注册生效。
- Goexit(): 结束调用该函数的当前go程。Goexit():之前注册的 defer都生效。
示例代码:
package mainimport ("fmt""runtime"`time`
)func test() {defer fmt.Println("退出子go程之前")// returnruntime.Goexit() // 退出当前go程。defer fmt.Println("退出子go程之后")
}func main() {fmt.Println("主go程开始执行")go func() {fmt.Println("父go程执行之前")// runtime.Goexit() 会确保defer执行defer fmt.Println("defer 父go程执行之后")go test()fmt.Println("父go程执行之后")}()fmt.Println("主go程结束执行")time.Sleep(time.Second)
}
runtime.GOMAXPROCS()
- 设置当前 进程使用的最大cpu核数。 返回 上一次调用成功的设置值。 首次调用返回默认值。
示例代码:
package mainimport ("fmt""runtime"
)func main() {fmt.Println(runtime.GOROOT())n := runtime.GOMAXPROCS(0) // 0表示最大fmt.Println("n = ", n) // 返回上次设置成功的设置值n = runtime.GOMAXPROCS(2)fmt.Println("n = ", n) // 16n = runtime.GOMAXPROCS(4)fmt.Println("n = ", n) // 2n = runtime.GOMAXPROCS(8)fmt.Println("n = ", n) // 4n = runtime.GOMAXPROCS(1)fmt.Println("n = ", n) // 8
}
补充知识点
- 每当有一个进程启动时,系统会自动打开三个文件: 标准输入、标准输出、标准错误。 —— 对应三个文件: stdin、stdout、stderr
- 当进行运行结束。操作系统自动关闭三个文件。
channel
- 是一种数据类型。 对应一个“管道”(通道 FIFO)
- channel的定义:
- make (chan 在channel中传递的数据类型, 容量)
- 容量= 0: 无缓冲channel
- 容量 > 0 :有缓冲channel
- make(chan int) 或 make (chan string , 0)
- make (chan 在channel中传递的数据类型, 容量)
- channel有两个端:
- 一端:写端(传入端) chan <-
- 另一端: 读端(传出端)<- chan
- 要求:读端和写端必须同时满足条件,才在shan上进行数据流动。否则,则阻塞。
- channel是一种先进先出(FIFO)的队列类型
示例代码
package mainimport ("fmt""time"
)// 全局定义channel, 用来完成数据同步
var flagChan = make(chan struct{}) // 空struct不占用空间// 定义一台打印机
func printer(s string) {for _, ch := range s {fmt.Printf("%c", ch) // 屏幕:stdouttime.Sleep(300 * time.Millisecond)}
}// 定义两个人使用打印机
func person1() { // person 先执行。printer("hello")flagChan <- struct{}{} // 写入数据,解除阻塞
}
func person2() { // person 后执行printer("world")flagChan <- struct{}{} // 写入数据,解除阻塞
}func main() {go person1()<-flagChan // 拿到数据之前,一直阻塞,所以会等到go程执行结束,直到写入go person2()<- flagChanfmt.Println("\n程序执行结束!!!")
}
Golang并发编程入门教程相关推荐
- Java并发编程实战_一线大厂架构师整理:java并发编程实践教程
并发编程是Java语言的重要特性之一, 在Java平台上提供了许多基本的并发功能来辅助开发多线程应用程序.然而,这些相对底层的并发功能与上层应用程序的并发语义之间并不存在一种简单而直观的映射关系.因此 ...
- 学习嵌入式的书籍推荐,嵌入式编程入门教程学习大纲
嵌入式系统是当前热门.具发展前景的IT应用领域之一,很多数字包括手机.电子字典.可视电话.数字相机.数字摄像机.机顶盒.智能玩具医疗仪器和航空航天设备等都是典型的嵌入式系统.越来越多的人想要了解学习嵌 ...
- 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记
<Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...
- python快速编程入门教程-终于懂得python快速编程入门教程
为了提高模块加载的速度,每个模块都会在__pycache__文件夹中放置该模块的预编译模块,命名为module.version.pyc,version是模块的预编译版本编码,一般都包含Python的版 ...
- 【转载】PHP面向对象(OOP)编程入门教程
面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持. 如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们 ...
- PHP面向对象(OOP)编程入门教程
面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...
- socket 编程入门教程(三)TCP原理:5、TCP的三次握手(three-way handshake)
socket 编程入门教程(三)TCP原理:5.TCP的三次握手(three-way handshake) 前面3个小节介绍了socket机制对TCP协议三次握手的实现,需要强调的是,与协议独立于实现 ...
- 《Delphi XE6 android 编程入门教程》推荐
近5.6年已经没有看见关于delphi的新技术的书出来了(看来在国内delphi的使用量确实很低了), 高勇同学最近出了一本<Delphi XE6 android 编程入门教程>,上周刚拿 ...
- 怎么查看电脑有没有python_python人工智能爬虫系列:怎么查看python版本_电脑计算机编程入门教程自学...
本文由简码编程原创,保留所有版权,转载请注明出处. 本python人工智能爬虫系列教程基于Python3.0版本, 将python结合windows桌面开发工具aardio一起做可视化的开发, 用py ...
最新文章
- SQL查找是否存在,别再count了!
- 【Linux 内核 内存管理】虚拟地址空间布局架构 ② ( 用户虚拟地址空间组成 | 内存描述符 mm_struct 结构体源码 )
- 收到一个机器人txt微盘_经阁-第一章 吞了个机器人-爱阅小说网
- linux java 文件夹创建失败_Linux文件夹文件创建、删除
- java 财付通支付_工商变更:马化腾卸任财付通支付科技有限公司法定代表人
- 自定义模块的查找方式
- MySQL server has gone away报错原因分析
- 三段话搞明白什么是Krylov子空间迭代法
- 在微型计算机中1G标准等于,微型计算机的基础知识概要.ppt
- bing翻译接口appID申请教程【TranslateApiException: AppId is over the quota 】
- 通达OA2013完美平台补丁以及手机短信服务配置
- 安卓手机上计算机的各按键功能,手机按键里那些你不知道的功能
- 桌面计算机找不到硬盘,bios找不到硬盘完美解决方法 选择STATConfigur
- 教你如何写初/高级前端简历
- socket多线程图形化界面聊天室实例
- PCB设计时应该考虑的几个问题
- WPS(word)批量给所有表格添加题注(标题)
- 四川大学计算机学院2016级毕业生,小猿分享 | 四年磨一剑:计算机学院2016级优秀毕业生高含宁专访...
- 勤于奋:国外LEAD账号申请细节
- 衡量两个向量相似度的方法:余弦相似度