GO入门——7. 并发
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. 并发的更多相关文章
- Golang 入门 : 理解并发与并行
Golang 的语法和运行时直接内置了对并发的支持.Golang 里的并发指的是能让某个函数独立于其他函数运行的能力.当一个函数创建为 goroutine 时,Golang 会将其视为一个独立的工作单 ...
- 从缓存入门到并发编程三要素详解 Java中 volatile 、final 等关键字解析案例
引入高速缓存概念 在计算机在执行程序时,以指令为单位来执行,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入. 由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这 ...
- Go 语言极速入门
本系列文章主要是记录<Go 语言实战>和<Google 资深工程师深度讲解 Go 语言>的学习笔记. Go 语言极速入门1 - 环境搭建与最简姿势Go 语言极速入门2 - 基础 ...
- jmeter安装教程与新手入门(附jdk安装教程)
一.前言 最近要对网站做性能测试,提到了并发数测试,查了下,还是决定使用jmeter来完成这项测试,这里总结了jmeter完整的安装教程,附上新手使用教程. 二.jmeter安装 1.jdk安装(jm ...
- Golang 入门 : 竞争条件
笔者在前文<Golang 入门 : 理解并发与并行>和<Golang 入门 : goroutine(协程)>中介绍了 Golang 对并发的原生支持以及 goroutine 的 ...
- Golang 入门 : goroutine(协程)
在操作系统中,执行体是个抽象的概念.与之对应的实体有进程.线程以及协程(coroutine).协程也叫轻量级的线程,与传统的进程和线程相比,协程的最大特点是 "轻"!可以轻松创建上 ...
- 太赞了!阿里几位工程师重写了 《Java 并发编程》
事情是这样的,前些日子和得知一个读者在准备阿里的面试,我蛮有兴趣的跟他聊了起来,随着话题越来越深入,我发现这位读者有意思,他和几位阿里的工程师之前编写了一本 concurrent.redspider. ...
- 如何深入学习Java并发编程?
在讲解深入学习Java并发编程的方法之前,先分析如下若干错误的观点和学习方法. 错误观点1:学习Java编程主要是学习多线程. 这话其实是说明了表面现象,多线程其实还真是并发编程的实现方式,但在实际高 ...
- Storm流计算从入门到精通之技术篇(高并发策略、批处理事务、Trident精解、运维监控、企业场景)
1.Storm全面.系统.深入讲解,采用最新的稳定版本Storm 0.9.0.1 : 2.注重实践,对较抽象难懂的技术点如Grouping策略.并发度及线程安全.批处理事务.DRPC.Storm ...
随机推荐
- canvas(五)createPattern
/** * Created by xianrongbin on 2017/3/9. * 图片填充 */ var dom = document.getElementById('clock'), ctx ...
- canvas(四) Gradient- demo
/** * Created by xianrongbin on 2017/3/9. */ /* strokeStyle 或 fillStyle 属性的值*/ /** * Demo1 创建线性渐变 */ ...
- Linux anaconda 内网 安装 卸载
安装并不难, 官网介绍的很清楚, 但每次到官网找安装方法不方便,我总结了本文(很全) 官网下载Linux版anaconda, 地址https://www.anaconda.com/download/# ...
- 定义java中的变量
四种类型 1.整数 2.小数 3.字符 4.布尔值 八种 整数(byte 字节1 范围-128~127 ) (short 字节 2) (int 字节4) (lon ...
- python基础之Day10
一.函数的返回值 1.什么是返回值返回值是一个函数的处理结果, 2.为什么要有返回值如果我们需要在程序中拿到函数的处理结果做进一步的处理,则需要函数必须有返回值 3.函数的返回值的应用函数的返回值用r ...
- ps高级磨皮的7个步骤
1.打开图片 2. 进入通道看红绿蓝哪个通道痘比较明显拖拽复制拷贝哪个通道! 3.选中拷贝的通道--执行滤镜--其他--高反差保留 4.在执行图像--计算(混合模式强光)--计算三次 5.选alpha ...
- [Python] Window机器上同时安装Python 2 和 Python 3,如何兼容切换使用?
不论python2还是python3,python可执行文件都叫python.exe,在cmd下输入python得到的版本号取决于环境变量里哪个版本的python路径更靠前. 切换的方法有3种(方法3 ...
- zeromq学习记录(一)最初的简单示例使用ZMQ_REQ ZMQ_REP
阅读zeromq guide的一些学习记录 zeromq官方例子 在VC下运行会有些跨平台的错误 我这里有做修改 稍后会发布出来 相关的代码与库 http://download.zeromq.org ...
- RQNOJ 1 明明的随机数
查重和排序,这里我用的set进行存储数据,利用了set的唯一性和自动性,方便了很多 #include <iostream> using namespace std; #include &l ...
- 简单了解下java中的堆、栈和方法区。
堆.栈.方法区 1,首先了解下java中的数据类型. ①java中的八大基本数据类型:boolean, char , byte, short, int, long , float , double. ...