1 并发

1.1 goroutine

Goroutine 奉行通过通信来共享内存,而不是共享内存来通信

  • goroutine 只是由官方实现的超级“线程池”而已。
  • 每个实例 4-5KB 的栈内存占用和由于实现机制而大幅

    减少的创建和销毁开销,是制造 Go 号称的高并发的根本原因。
  • goroutine 的简单易用,也在语言层面上给予了开发者巨大的便利

1.2 Channel

  • Channel 是 goroutine -沟通的桥梁,大都是阻塞同步的
  • 通过 make 创建,close 关闭
  • Channel 是引用类型
  • 可以使用 for range 来迭代不断操作 channel
  • 可以设置单向或双向通道
  • 可以设置缓存大小,在未被填满前不会发生阻塞

1.3 Select

  • 可处理一个或多个 channel 的发送与接收
  • 同时有多个可用的 channel时按随机顺序处理
  • 可用空的 select 来阻塞 main 函数
  • 可设置超时
package main

import (
"fmt"
"runtime"
"sync"
"time"
) func main() {
testSelectTimeout()
} func testMain() {
//当只执行这一句时没有结果输出
//原因在于go将函数放入其他线程执行,当main结束后其他线程也将结束
go func() {
fmt.Println("Go GO GO !!!")
}()
} //channel是引用类型,所以不需要传指针类型即可修改
func goFunc(c chan bool) {
fmt.Println("GO GO GO")
c <- true
} //channel
func testChannel() {
//make(chan bool,x),设置缓存为x
//当有缓存时,如果缓存还没满则向channel插入值是不会阻塞的
//创建无缓存的channel
c := make(chan bool)
go goFunc(c)
//此时从channel中取值,如果channel中没有值则将阻塞
//因此必然将先执行完goFunc然后main才结束
<-c
} //channel配合range
func testChannelRange() {
c := make(chan bool)
go func() {
fmt.Println("GO GO GO")
c <- true
close(c) //关闭channel,如果不关闭range将一直阻塞main线程
}()
for v := range c { //从channel中一直取值,直到channel被关闭
fmt.Println(v) //输出true
}
} //
func testCurrentByChannel() {
//设置GO使用cup核数,好像默认就是多核
runtime.GOMAXPROCS(runtime.NumCPU())
c := make(chan bool, 10)
f := func(index int) {
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
fmt.Println(index, sum)
c <- true
}
for i := 0; i < 10; i++ {
go f(i)
}
for i := 0; i < 10; i++ {
<-c
}
} //WaitGroup类似java中的CountDownLatch
func testCurrentByWatiGroup() {
//设置GO使用cup核数,好像默认就是多核
runtime.GOMAXPROCS(runtime.NumCPU())
wg := sync.WaitGroup{}
wg.Add(10)
//需要传入指针
f := func(index int, wg *sync.WaitGroup) {
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
fmt.Println(index, sum)
wg.Done()
}
for i := 0; i < 10; i++ {
go f(i, &wg)
}
wg.Wait()
} //有问题。。。。
//当channel都无缓存时关闭其中一个channel,再向另一个写值,此时将发生死锁
//当channel有缓存,关闭的那个channel将一直输出(空,false)
func testSelect() {
//select 无法保证多个channel都关闭
c1, c2 := make(chan int), make(chan bool)
o := make(chan bool)
go func() {
//f1, f2 := false, false
for {
select {
//当某个channel关闭后,其case将一直执行,返回一个(v=空值,ok=false)
//因此此时select将
case v, ok := <-c1:
{
fmt.Println("oc1")
if !ok {
fmt.Println("c1")
o <- true
break
}
fmt.Println("c1", v)
}
case v, ok := <-c2:
{
if !ok {
o <- true
break
}
fmt.Println("c2", v)
}
}
}
}()
c1 <- 0
c1 <- 1
c2 <- true
c1 <- 2
c2 <- false
c1 <- 3 close(c1)
//close(c2)
c2 <- false
//c2 <- false
for i := 0; i < 2; i++ {
<-o
fmt.Println("o")
} } //select作为发送者
func testSelectSend() {
c := make(chan int) go func() {
for i := 0; i < 10; i++ {
//随机向c中写入0或1
select {
case c <- 0:
case c <- 1:
}
}
}()
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
select {} //阻塞程序
} //select timeout
func testSelectTimeout() {
c := make(chan int)
go func() {
for i := 0; i < 5; i++ {
time.Sleep(1 * time.Second)
c <- i
} }()
Label:
for {//不加for则只会输出一次case的匹配就结束了
select {
case v := <-c:
fmt.Println(v)
case <-time.After(3 * time.Second): //3s没获取到值时将执行
fmt.Println("Timeout") //输出
break Label //退出select死循环
}
}
}

GO入门——7. 并发的更多相关文章

  1. Golang 入门 : 理解并发与并行

    Golang 的语法和运行时直接内置了对并发的支持.Golang 里的并发指的是能让某个函数独立于其他函数运行的能力.当一个函数创建为 goroutine 时,Golang 会将其视为一个独立的工作单 ...

  2. 从缓存入门到并发编程三要素详解 Java中 volatile 、final 等关键字解析案例

    引入高速缓存概念 在计算机在执行程序时,以指令为单位来执行,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入. 由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这 ...

  3. Go 语言极速入门

    本系列文章主要是记录<Go 语言实战>和<Google 资深工程师深度讲解 Go 语言>的学习笔记. Go 语言极速入门1 - 环境搭建与最简姿势Go 语言极速入门2 - 基础 ...

  4. jmeter安装教程与新手入门(附jdk安装教程)

    一.前言 最近要对网站做性能测试,提到了并发数测试,查了下,还是决定使用jmeter来完成这项测试,这里总结了jmeter完整的安装教程,附上新手使用教程. 二.jmeter安装 1.jdk安装(jm ...

  5. Golang 入门 : 竞争条件

    笔者在前文<Golang 入门 : 理解并发与并行>和<Golang 入门 : goroutine(协程)>中介绍了 Golang 对并发的原生支持以及 goroutine 的 ...

  6. Golang 入门 : goroutine(协程)

    在操作系统中,执行体是个抽象的概念.与之对应的实体有进程.线程以及协程(coroutine).协程也叫轻量级的线程,与传统的进程和线程相比,协程的最大特点是 "轻"!可以轻松创建上 ...

  7. 太赞了!阿里几位工程师重写了 《Java 并发编程》

    事情是这样的,前些日子和得知一个读者在准备阿里的面试,我蛮有兴趣的跟他聊了起来,随着话题越来越深入,我发现这位读者有意思,他和几位阿里的工程师之前编写了一本 concurrent.redspider. ...

  8. 如何深入学习Java并发编程?

    在讲解深入学习Java并发编程的方法之前,先分析如下若干错误的观点和学习方法. 错误观点1:学习Java编程主要是学习多线程. 这话其实是说明了表面现象,多线程其实还真是并发编程的实现方式,但在实际高 ...

  9. Storm流计算从入门到精通之技术篇(高并发策略、批处理事务、Trident精解、运维监控、企业场景)

    1.Storm全面.系统.深入讲解,采用最新的稳定版本Storm 0.9.0.1 :   2.注重实践,对较抽象难懂的技术点如Grouping策略.并发度及线程安全.批处理事务.DRPC.Storm ...

随机推荐

  1. Centos7+hadoop2.7.3+jdk1.8

     修改主机名 1.       修改主机名 vi /etc/sysconfig/network ,改为 master , slave1 , slave2 2.       source /etc/sy ...

  2. jquery.validate.js的简单示例

    一.官方资料 官网 github 二.html <!DOCTYPE html> <html> <head> <meta charset="utf-8 ...

  3. rabbitmq shovel插件

    官网说明https://www.rabbitmq.com/shovel.html#management-status 启用shovel插件命令: rabbitmq-plugins enable rab ...

  4. small_trick_on_IT/PC

    1.浏览器下ctrl+F可实现文本查找 其余还有 2.将软件目录放到环境变量Path下,Ctrl+R输入.exe软件名即可调用. (tips:可把常用软件建立快捷方式,统一放在某一目录下噢!)

  5. nginx图解

    1.Http代理,反向代理:作为web服务器最常用的功能之一,尤其是反向代理. 这里我给来2张图,对正向代理与反响代理做个诠释,具体细节,大家可以翻阅下资料. Nginx在做反向代理时,提供性能稳定, ...

  6. CDH版本的hadoop下载

    http://archive.cloudera.com/cdh5/cdh/5/加要下载的cdh版本插件 例如: http://archive.cloudera.com/cdh5/cdh/5/zooke ...

  7. vue-学习系列之vue双向绑定原理

    一.访问器属性 访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过 defineProperty() 方法单独定义. var obj = { }; // 为obj定义一个名为 hel ...

  8. HashMap TreeMap的区别

    Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复就覆盖了),但允许值重复.Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快 ...

  9. Axure RP Xmind

    官方网站下载地址:http://www.axure.com/download 下载地址:http://www.iaxure.com/2941.html 汉化安装:http://www.iaxure.c ...

  10. jupyter Notebook环境搭建

    1.什么是jupyter notebook jupyter notebook是一种 Web 应用,能让用户将说明文本.数学方程.代码和可视化内容全部组合到一个易于共享的文档中.它可以直接在代码旁写出叙 ...