假设我们现在有这么一个需求:

计算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--协程之间通信的方式的更多相关文章

  1. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  2. golang:Channel协程间通信

    channel是Go语言中的一个核心数据类型,channel是一个数据类型,主要用来解决协程的同步问题以及协程之间数据共享(数据传递)的问题.在并发核心单元通过它就可以发送或者接收数据进行通讯,这在一 ...

  3. (四十二)golang--管道

    假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ...

  4. Go 通道(channel)与协程间通信

    协程间通信 协程中可以使用共享变量来通信,但是很不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难. 在 Go 中有一种特殊的类型,通道(channel),就像一个可以用于发送类型化数据的 ...

  5. NeHe OpenGL教程 第四十二课:多重视口

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. 网站开发进阶(四十二)巧用clear:both

    网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...

  7. Gradle 1.12用户指南翻译——第四十二章. Announce插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  8. SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关

    0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...

  9. “全栈2019”Java第四十二章:静态代码块与初始化顺序

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. H5混合应用之X5内核

    一.X5内核介绍 X5内核是腾讯公司基于优秀开源 webkit 深度优化的浏览器渲染引擎,并且在2014年正式宣布开放给app开发者,所以现在可以在很多app上看到都是使用的X5内核实现Hybrid混 ...

  2. attention 汇总(持续)

    Seq2seq Attention Normal Attention 1.  在decoder端,encoder state要进行一个线性变换,得到r1,可以用全连接,可以用conv,取决于自己,这里 ...

  3. element UI 调整表格行高

    使用element UI的table默认属性,绘制表格如下: 该表格的行高太大了,于是想调小一些. 查看官网的文档,table有几个属性, row-style:行的 style 的回调方法,也可以使用 ...

  4. Scala,Java,Python 3种语言编写Spark WordCount示例

    首先,我先定义一个文件,hello.txt,里面的内容如下: hello sparkhello hadoophello flinkhello storm Scala方式 scala版本是2.11.8. ...

  5. Think in Speed (关于速度的一点思考)

    天下武功,无坚不摧,唯快不破!所以我们重视速度没毛病! 老话说:不要过早优化.赞同! 我们在写代码过程中,有时可能就是为了追求所谓的性能,然后,就给自己挖坑了. 关于开发速度,我有以下几点思考: 1. ...

  6. wpf datagrid field to image converter 字段 图片转化器

    <DataGridTemplateColumn Header="Binding"> <DataGridTemplateColumn.CellTemplate> ...

  7. 我用python爬取了知乎Top沙雕问题排行榜

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 数据森麟 PS:如有需要Python学习资料的小伙伴可以加点击下方 ...

  8. 用PHP写出计算器

    <body> <?php if (!empty($_POST)) { $op=$_POST['point']; $sum1 = $_POST['sum1']; $sum2 = $_P ...

  9. 升鲜宝V2.0_杭州生鲜配送行业,条码标签管理之批量打印标签与分配配送任务相关操作说明_升鲜宝生鲜配送系统_15382353715_余东升

       升鲜宝V2.0_杭州生鲜配送行业,条码标签管理之批量打印标签与分配配送任务相关操作说明_升鲜宝供应链管理生鲜配送系统    题外话,随着国家对食材安全这个行业重视性越来越强,最近国家又出具了一些 ...

  10. 登陆远程服务器的Tomcat 8的manger的页面403

    访问远程服务器Tomcat 8的管理页面报错 在远程服务器上安装了一个tomcat8.5,配置好用户后重新启动tomcat ,发现:8080可以访问,但是进入:8080/manager/html页面报 ...