Go语言管道与高并发实战
固定时长定时器
- 写法一
package mainimport ("fmt""time"
)func main() {//创建3秒定时器timer := time.NewTimer(3*time.Second)fmt.Println("定时器创建完毕")//打印当前时间fmt.Println(time.Now())x := <-timer.Cfmt.Println(x)
}
2) 写法二
package mainimport ("fmt""time"
)func main() {//打印当前时间fmt.Println(time.Now())x := <-time.After(3*time.Second)fmt.Println("定时器创建完毕")
}
周期性长定时器
package mainimport ("fmt""time"
)func main() {//创建一个1秒为周期的秒表ticker := time.NewTicker(1 * time.Second)var i intfor {//每隔1秒读出当前时间x := <-ticker.Cfmt.Print("\n", x)//10秒后停止计时并退出i++if i > 9 {ticker.Stop()break}}fmt.Println("计时结束")
}
定时器的终止和重置
package mainimport ("time""fmt"
)func main() {timer := time.NewTimer(3 * time.Second)fmt.Println(time.Now(), "炸弹将于3秒后引爆")//趁定时器未到时间,将定时器终止timer.Stop()fmt.Println("炸弹已被拆除,定时器失效")//定时器已被叫停,其时间管道永远读不出数据了--死锁//fatal error: all goroutines are asleep - deadlock!t := <-timer.Cfmt.Println("炸弹引爆于", t)
}
等待组
package mainimport ("fmt""sync""time"
)func main041() {//创建任务等待组var wg sync.WaitGroup//向等待组中添加任务wg.Add(1)wg.Add(1)wg.Add(1)//从等待组中抹掉任务wg.Done()wg.Done()wg.Done()//阻塞等待至等待组中的任务数为0wg.Wait()}func main() {var wg sync.WaitGroupwg.Add(1)go func() {for i := 0; i < 5; i++ {fmt.Println("子协程1", i)<-time.After(1 * time.Second)}fmt.Println("子协程1结束任务")wg.Done()}()wg.Add(1)go func() {var i intticker := time.NewTicker(1 * time.Second)for {<-ticker.Ci++fmt.Println("子协程2", "秒表:", i)if i > 9 {break}}fmt.Println("子协程2结束任务")wg.Done()}()//等待组阻塞等待至记录清零为止wg.Wait()fmt.Println("END")
}
互斥锁
1)并发安全问题,每次累加数据都不一样
package mainimport ("fmt""sync"
)func main() {//创建任务等待组var wg sync.WaitGroupvar money = 2000for i := 0; i < 10; i++ {wg.Add(1)go func() {//并发安全问题,每次累加数据都不一样for j := 0; j < 10000; j++ {money += 1}wg.Done()}()}//阻塞等待至等待组中的任务数为0wg.Wait()fmt.Println("最终金额", money)
}
2)加互斥锁
package mainimport ("fmt""sync""time"
)var wg sync.WaitGroupfunc main() {var money = 2000//一支麦克var mt sync.Mutexwg.Add(1)go func() {fmt.Println("鹤姐开始抢麦")//谁抢到麦谁才有资格修改money,其他抢麦的协程就必须阻塞等待mt.Lock()fmt.Println("鹤姐抢到了麦,何洁开始嗨")money -= 300<-time.After(10*time.Second)//曲罢弃麦,其它人再去哄抢mt.Unlock()fmt.Println("鹤姐弃麦")wg.Done()}()wg.Add(1)go func() {fmt.Println("鹤哥开始抢麦")//谁抢到麦谁才有资格修改money,其他抢麦的协程就必须阻塞等待mt.Lock()fmt.Println("鹤哥抢到了麦,鹤哥开始嗨")money -= 500<-time.After(10*time.Second)//曲罢弃麦,其它人再去哄抢mt.Unlock()fmt.Println("鹤哥弃麦")wg.Done()}()/*不抢麦的人不会被阻塞*/wg.Add(1)go func() {fmt.Println("abcdefg")<-time.After(1*time.Second)fmt.Println("hijklmn")<-time.After(1*time.Second)fmt.Println("opqrst")<-time.After(1*time.Second)fmt.Println("uvwxyz")wg.Done()}()wg.Wait()
}
信号量控制最大并发数
控制最大并发数量
package mainimport ("fmt""math""sync""time"
)var wg08 sync.WaitGroup
var chSem chan intfunc main() {//semaphore信号量chSem = make(chan int, 5)for i := 0; i < 100; i++ {wg08.Add(1)go getSqrt(i)}wg08.Wait()
}func getSqrt(n int) {//规定:所有并发任务都必须注册在信号量管道里chSem <- nfmt.Printf("%d的平方根是%.2f\n", n, math.Sqrt(float64(n)))<- time.After(10 * time.Second)//任务结束后从信号量管道注销,给其它腾出空间<-chSemwg08.Done()
}
死锁现象
1)自己阻塞自己
package mainimport "fmt"//自己阻塞自己
func main() {ch := make(chan int, 0)ch <- 123x := <-chfmt.Println(x)
}
2)开塞露协程-开晚了
package mainimport "fmt"
//开塞露协程-开晚了
func main() {ch := make(chan int, 0)ch <- 123go func() {x := <-chfmt.Println(x)}()
}
3)管道读写时,相互要求对方先读/写,自己在写/读,造成死锁
package mainimport ("fmt"
)/*读写锁定相互阻塞,形成隐形死锁*/
func main() {chHusband := make(chan int, 0)chWife := make(chan int, 0)//老公go func() {for{select {//只要我有钱我就给你发红包case <- chHusband:chWife <- 123fmt.Println("老公:我已经给你发123元红包了")case chWife <- 1:fmt.Println("老公:我已经给你发1元红包了")}}}()//老婆select {//只要我有钱我就给你发红包case <- chWife:chHusband <- 123fmt.Println("老婆:我已经给你发123元红包了")}fmt.Println("THE END")}
4)读写锁定相互阻塞,形成隐形死锁
package mainimport ("fmt""runtime""sync"
)/*读写锁定相互阻塞,形成隐形死锁*/
func main() {var rwm09 sync.RWMutexch := make(chan int, 0)//子协程负责写入go func() {//连锁都抢不到555...rwm09.Lock()ch <- 123rwm09.Unlock()}()go func() {//本协程负责读出rwm09.RLock()//只要读不到内容就永远阻塞x := <-chfmt.Println("读到", x)rwm09.RUnlock()}()for {//通知垃圾回收器来清理垃圾(即使不叫也会定时清理)runtime.GC()}}
Go语言管道与高并发实战相关推荐
- 如何使用 Go 语言搭建企业级高并发服务器?
每到节假日和过年,需要外出通行的人几乎都会遇到一个问题:抢火车票!当全国上亿人都在固定的时间段抢票,服务器动辄就要承受上百万级并发的情况时,你就会明白,一个支持高并发的服务器架构有多重要! 在后端程序 ...
- java高并发实战Netty+协程(Fiber)|系列1|事件驱动模式和零拷贝
今天开始写一些高并发实战系列. 本系列主要讲两大主流框架: Netty和Quasar(java纤程库) 先介绍netty吧,netty是业界比较成熟的高性能异步NIO框架. 简单来说,它就是对NIO2 ...
- 高并发实战2---手写计算器缓存
对于初级版本(高并发实战1)的提升一级优化 不直接缓存计算结果,而是缓存计算任务(future可以阻塞线程),当没有从缓存中读到正在执行计算的任务的时候,直接阻塞等待正在执行的任务计算的结果,然后读取 ...
- java系统优化方案_Java秒杀系统方案优化 高性能高并发实战-一号门
类别: 视频 语言: Java 发布日期: 2019-03-02 介绍:以"秒杀"这一Java高性能高并发的试金石场景为例,带你通过一系列系统级优化,学会应对高并发. 第1章 课程 ...
- 《Netty、Redis、Zookeeper高并发实战》2️⃣高并发IO的底层原理
文章目录 1.IO读写的基础原理 1.1 内核缓冲区与进程缓存区 1.2 详解典型的系统调用流程 2.四种主要的IO模型 2.1 同步阻塞IO(Blocking IO) 2.2 同步非阻塞IO(Non ...
- 慕课网高并发实战(一)-并发与高并发基本概念
课程网址 并发: 同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程交替得换入或者换出内存,这些线程是同时"存在"的,每个线程都处于执行过程中的某个状态,如果运行在多核 ...
- Redis 的高并发实战:抢购系统 --浅奕
简介: 主要内容: 一.IO 模型和问题 二.资源竞争与分布式锁 三.Redis 抢购系统实例 主要内容: 一.IO 模型和问题 二.资源竞争与分布式锁 三.Redis 抢购系统实例 一.IO 模型和 ...
- Java秒杀系统方案优化 高性能高并发实战 学习笔记
秒杀系统 (一)搭建环境 自定义封装Result类 自定义封装CodeMsg类 集成redis和rabbit 封装RedisService类 断言和日志测试 (二)实现用户登录和分布式Session ...
- Java高性能高并发实战之页面优化技术(五)
文章目录 前言 正文 增加缓存 页面静态化,前后端分离 页面缓存 实际操作 URL缓存 对象缓存 具体实现思想 具体实现过程 页面静态化 后记 前言 此篇文章是系列的第五章篇文章,具体文章目录: 章节 ...
最新文章
- 【学习笔记】20、日期和时间模快
- Linux 之三 静态库及动态库的编写和使用
- 北京林业大学计算机技术复试,北京林业大学计算机应用技术04年考研复试办法...
- 不安装cudnn可不可以_关于CUDA和cuDNN的安装
- html5填空题阅卷,“过五关”般严格,高考阅卷老师来自哪里?研究生参与阅卷?
- 国产木乃伊走进CTO编辑部
- html5实现饼图和线图-我们到底能走多远系列(34)
- PermissionError: [Errno 13] in python
- PHP文件系统-文件路径操作和权限
- 普林斯顿大学计算机系,普林斯顿大学计算机科学系
- BAPI:KBPP_EXTERN_UPDATE_CO, TCODE:CJ30/CJ40 第一部分
- 网络配置管理大大减轻网络管理员的负担
- Pycharm初识JS
- [ 资料分享 ] Vue 源码分析与讲解 - 附下载地址
- 微信步数修改.html,httpCatcher,charles修改微信步数,支付宝森林能量满满
- oracle查询备份存储路径,Oracle 数据库备份与恢复(RMAN介绍一)
- flutter2.x报错解决type (RouteSettings) => Route<dynamic> is not a subtype of type (RouteSettings) => Rou
- Python基础刷题,期末不挂科~~~(已完结)
- Openfire 即时通讯系统(服务器端+Android客户端)一
- phyton计算每天进步的力量