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 ...
随机推荐
- crontab命令详解 含启动/重启/停止
linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所以, ...
- 解决安装xcode后git使用报错的问题
一.现象: htmlxdeMacBook-Pro:demo htmlx$ git status Agreeing to the Xcode/iOS license requires admin pri ...
- Win10电脑系统使用技巧
现如今,电脑已经成为我们不可或缺的伙伴,陪伴着我们的工作.娱乐和生活,而Windows10在大家使用的电脑中占据了大多数,但是很多的小伙伴对它的许多功能并不真正了解,今天小编就带大家了解一下这些技巧, ...
- C++学习札记(2)
重载构造函数 #include <iostream> using namespace std; class rectangle { public: rectangle(){cout< ...
- Spring 的属性注入
一.注入方式 (1)set方法注入 (2)构造函数注入 (3)p名称空间注入 (4)spel注入 二.复杂类型注入
- MFC在对话框中嵌入对话框
在对话框中嵌入子对话框 代码 m_childDlg = new CChildDlg(); m_childDlg->Create(IDD_CHILD_DIALOG,AfxGetApp()-> ...
- 结构体struct、联合体union、枚举类型enum
1.c语言中的类型 1)内置类型——char,short,int,float,double: 2)用户自定义类型(UDT)——struct结构体,union联合体,enum枚举类型 2.内存对齐 2. ...
- okhttp 调用相机 上传服务器
MainActivity package com.bwie.lianxi1; import android.content.Intent; import android.database.Cursor ...
- 高性能mysql-锁的调试
锁的调试分为俩部分,一是服务器级别的锁的调试.二是存储引擎级别的锁的调试 对于服务器级别的锁的调试: 服务器级别的锁的类型有表锁,全局锁,命名锁,字符锁 调试命令: Show processlist ...
- Android Studio中的大量findViewById
一. 分析 在Android Studio中开发时,findViewById是用的最多的函数之一.经常需要对返回的view进行类型转换,输入麻烦.代码丑陋. 本文提供两种方案来解决这个问题: 1.安装 ...