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 ...
随机推荐
- react项目请求数据的fetch的使用
准备三个文件(封装请求函数),然后测试一下,能不能调用数据 第一个文件 request.js import 'whatwg-fetch'; /** * Parses the JSON returne ...
- 16. pt-mysql-summary
pt-mysql-summary --host=192.168.100.101 --port=3306 --user=admin --password=admin \ pt-mysql-summary ...
- [BeijingWc2008]雷涛的小猫
--BZOJ1270 Description 雷涛的小猫雷涛同学非常的有爱心,在他的宿舍里,养着一只因为受伤被救助的小猫(当然,这样的行为是违反学生宿舍管理条例的). 在他的照顾下,小猫很快恢复了健康 ...
- Spring Boot-右键maven build成功但是直接运行main方法出错的解决方案
1.代码就一个Controller,从官网复制过来的,如下 package com.springboot.controller; import org.springframework.boot.Spr ...
- C++ 提取网页内容系列之五 整合爬取豆瓣读书
工作太忙 没有时间细化了 就说说 主要内容吧 下载和分析漫画是分开的 下载豆瓣漫画页面是使用之前的文章的代码 见http://www.cnblogs.com/itdef/p/4171179.html ...
- 【ZooKeeper】ZooKeeper安装及简单操作
ZooKeeper介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一 ...
- # 2019-2020-3 《Java 程序设计》第四周总结
2019-2020-3 <Java 程序设计>第四周知识总结 第五章:继承 1.定义继承关系的语法结构: [修饰符] class 子类名 extends 父类名 { 类体定义 } 父类中应 ...
- sass基础常用指南
一.变量 $global-color:red; .nav{ background:$global-color; } 二.sass命名时横杠和下划线不区分 $global-color:yellow; . ...
- LVS、Nginx 及 HAProxy 工作原理
当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web 应用服务器集群,也可以是数据库服务器集群,还可以是分布式缓存服务器 ...
- orabbix监控oracle
Orabbix 是一个用来监控 Oracle 数据库实例的 Zabbix 插件.下载地址: http://www.smartmarmot.com/product/orabbix/download/ O ...