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. SpringBoot集成Jasypt安全框架,配置文件内容加密

    我们在SpringBoot项目中的yml或者properties配置文件中都是明文的,相对而言安全性就低了很多.都知道配置文件中的都是一些数据库连接用户名密码啊.一些第三方密钥等信息.所以我们谨慎点, ...

  2. [leetcode]5. Longest Palindromic Substring最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  3. java_18 Collection接口

    1.Collection接口 Collection 层次结构 中的根接口.Collection 表示一组对象,这些对象也称为 collection 的元素.一些 collection 允许有重复的元素 ...

  4. Python爬虫项目--爬取链家热门城市新房

    本次实战是利用爬虫爬取链家的新房(声明: 内容仅用于学习交流, 请勿用作商业用途) 环境 win8, python 3.7, pycharm 正文 1. 目标网站分析 通过分析, 找出相关url, 确 ...

  5. NC 自定义参照类

    package nc.ui.hzctr.costctr.ref; import nc.ui.bd.ref.AbstractRefModel; import nc.vo.pubapp.pattern.p ...

  6. leveldb 源码编译 vs版本

    为什么要windows版本? 因为方便调试跟进 VS的体验真的很不错. 搜索了一段时间才发现GITHUB有windows版本的leveldb 但是使用VS编译也有不少坑 可以下载网络上的其他朋友的版本 ...

  7. 为什么说Redis是单线程的以及Redis为什么这么快!

    参考文章:https://blog.csdn.net/xlgen157387/article/details/79470556 redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用 ...

  8. Object.defineProperty之observe实现

    对数据对象的属性批量劫持设置: <script type="text/javascript"> function observe(data){ if(!data || ...

  9. Oracle使用JDBC进行增删改查 表是否存在

    Oracle使用JDBC进行增删改查 数据库和表 table USERS (   USERNAME VARCHAR2(20) not null,   PASSWORD VARCHAR2(20) ) a ...

  10. 第一次使用zxxbox弹层经历

    一:首先这个插件是基于JQuery的插件,要先导入JQuery,然后再导入这个插件 二:HTML部分 <a href="http://www.jisuapi.com/static/im ...