(四十二)golang--协程之间通信的方式
假设我们现在有这么一个需求:
计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime。
分析:
(1)使用goroutime完成,效率高,但是会出现并发/并行安全问题;
(2)不同协程之间如何通信;
- 对于(1):不同协程之间可能同时对一块内存进行操作,导致数据的混乱,即并发/并行不安全;主协程运行完了,计算阶乘的协程却没有运行完,功能并不能够准确实现;可利用互斥锁解决该问题;
- 对于(2):可以利用利用管道;
正常的代码:
package main import (
"fmt"
"sync"
) var (
myMap = make(map[int]int, )
) func cal(n int) {
res :=
for i := ; i <= n; i++ {
res *= i
}
myMap[n] = res
} func main() {
for i := ; i <= ; i++ {
go cal(i)
}
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
}
运行结果:

1.利用互斥锁
package main import (
"fmt"
"sync"
""
) var (
myMap = make(map[int]int, )
//lock是全局互斥锁,synchornized
lock sync.Mutex
) func cal(n int) {
res :=
for i := ; i <= n; i++ {
res *= i
}
lock.Lock()
myMap[n] = res
lock.Unlock()
} func main() {
for i := ; i <= ; i++ {
go cal(i)
} for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
}

有可能主程序运行完了而cal还没运行完(上面结果只到13,没有14,15),需要加上time.Sleep(time.Seconde*3),而在输出时,由于主协程并不知道程序已经完成了,底层仍然可能出现竞争资源,所以在输出阶段也要加上互斥锁。最终代码如下:
package main import (
"fmt"
"sync"
) var (
myMap = make(map[int]int, )
//lock是全局互斥锁,synchornized
lock sync.Mutex
) func cal(n int) {
res :=
for i := ; i <= n; i++ {
res *= i
}
lock.Lock()
myMap[n] = res
lock.Unlock()
} func main() {
for i := ; i <= ; i++ {
go cal(i)
} time.Sleep(time.Second * 4) lock.Lock()
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
lock.Unlock()
}
为什么需要管道?
(1)主线程在等待所有协程全部完成的时间很难确定;
(2)如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能协程还处于工作状态,这时也会随着主协程的结束而销毁;
(3)通过全局变量加锁同步来实现通讯,也并不利于多个协程对全局变量的读写操作;
管道的介绍:
(1)管道的本质就是一种数据结构--队列;
(2)数据先进先出;
(3)线程安全,多协程访问时,不需要加锁;
(4)管道只能存储相同的数据类型;
管道的声明:
var intChan chan int;
var stringChan chan string;
var mapChan chan map[int]string;
var perChan chan Person;
var perChan chan *Person;
注意:管道是引用类型;管道必须初始化后才能写入数据;管道是有类型的,即IntChan只能写入int;
管道初始化:
var intChan chan int
intChan = make(chan int,10)
向管道中读写数据:
num := 10
intChan<-num
var num2 int
num2<-intChan
注意:管道容量满了则不能继续写入,在没有使用协程的情况下,管道空了不能继续读取。
如何使管道中存储任意数据类型?

(四十二)golang--协程之间通信的方式的更多相关文章
- Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式
		Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ... 
- golang:Channel协程间通信
		channel是Go语言中的一个核心数据类型,channel是一个数据类型,主要用来解决协程的同步问题以及协程之间数据共享(数据传递)的问题.在并发核心单元通过它就可以发送或者接收数据进行通讯,这在一 ... 
- (四十二)golang--管道
		假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ... 
- Go 通道(channel)与协程间通信
		协程间通信 协程中可以使用共享变量来通信,但是很不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难. 在 Go 中有一种特殊的类型,通道(channel),就像一个可以用于发送类型化数据的 ... 
- NeHe OpenGL教程 第四十二课:多重视口
		转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ... 
- 网站开发进阶(四十二)巧用clear:both
		网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ... 
- Gradle 1.12用户指南翻译——第四十二章. Announce插件
		本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ... 
- SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关
		0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ... 
- “全栈2019”Java第四十二章:静态代码块与初始化顺序
		难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ... 
随机推荐
- yii2关联表
			asArray()这个方法很好用,返回数组是1版本想要的形式,这种方式有种tp框架的感觉 
- python做中学(六)os.getcwd() 的用法
			概述 os.getcwd() 方法用于返回当前工作目录. 语法 getcwd()方法语法格式如下: os.getcwd() 参数 无 返回值 返回当前进程的工作目录. 实例 以下实例演示了 getcw ... 
- 【mysql报错】[Err] 1248 - Every derived table must have its own alias
			当我运行一条联合查询的sql语句时报如下错误: [Err] 1248 - Every derived table must have its own alias,大概意思是每一张派生表必须要有自己的别 ... 
- Mysql 5.7:更改密码时出现ERROR 1054 (42S22): Unknown column 'password' in 'field list'
			1.环境 在新服务器上重新安装了环境,原来是5.6的,就升级到了5.7版本. 2.问题 新安装的MySQL5.7,登录时提示密码错误,安装的时候并没有更改密码,后来通过免密码登录的方式更改密码. 输入 ... 
- 几个高逼格 Linux 命令!
			作者:忧郁巫师 https://dwz.cn/A1FOjLXk 1. sl 命令 你会看到一辆火车从屏幕右边开往左边…… 安装 $ sudo apt-get install sl 运行 $ sl 命令 ... 
- 基于 EntityFramework 生成 Repository 模式代码
			借助 WeihanLi.EntityFramework 实现简单的 Repository Intro 很多时候一些简单的业务都是简单的增删改查,动态生成一些代码完成基本的增删改查,而这些增删改查代码大 ... 
- 项目中出现多个域名下的Cookie
			前言:我们在查看一个项目的Cookie时,有时会看到多个域名下的Cookie,如下图: 其中一种常见的原因是:因为我们在项目中引用了另一个项目的资源.如下图: 重点:浏览器的一种默认机制:如果我们引用 ... 
- 设计模式-单例模式(winfrom带参)
			一.单例模式 就是在整个代码全局中,只有一个实例.比如Log4.NET或者窗体程序. 二.实战演练 通过字段cSOCode获取窗体,窗体只有一个且cSOCode值不同获取的窗体也不同. private ... 
- Docker基础概念与安装
			Docker是什么? Docker最初是dotCloud公司的创始人Solomon Hyks在法国期间发起的一个公司内部项目,它是基于dotCloud公司多年云服务技术的一次革新,并于2013年3月以 ... 
- HTML5新标签与特性---新表单+新属性----综合案例1
			HTML5新标签与特性 兼容性问题 (ie9 以上的版本) 文档类型设定 document HTML: sublime 输入 html:4s XHTML: sublime 输入 html:xt HTM ... 
