go基础之并发
1、Goroutines是轻量级线程
go语句在单独的线程中运行一个函数。
你可以使用go语句启动一个新的执行线程,即一个goroutine。它在一个不同的,新创建的goroutine中运行一个函数。 单个程序中的所有goroutine共享相同的地址空间。
go list.Sort() // Run list.Sort in parallel; don’t wait for it.
以下程序将打印“Hello from main goroutine”。它也可能打印出“来自另一个goroutine的Hello”,这取决于两个goroutine中的哪一个先完成。
func main() {
go fmt.Println("Hello from another goroutine")
fmt.Println("Hello from main goroutine")
// At this point the program execution stops and all
// active goroutines are killed.
}
下一个程序很可能会打印“Hello from main goroutine”和“Hello from another goroutine”。 它们可以按任何顺序打印。 另一种可能性是第二个goroutine非常慢并且在程序结束之前不打印它的消息。
func main() {
go fmt.Println("Hello from another goroutine")
fmt.Println("Hello from main goroutine")
time.Sleep(time.Second) // give the other goroutine time to finish
}
这是一个更直接的例子,我们定义一个使用并发来推迟事件的函数。
// Publish prints text to stdout after the given time has expired.
// It doesn’t block but returns right away.
func Publish(text string, delay time.Duration) {
go func() {
time.Sleep(delay)
fmt.Println("BREAKING NEWS:", text)
}() // Note the parentheses. We must call the anonymous function.
}
下面是Publish函数的使用示例
func main() {
Publish("A goroutine starts a new thread.", 5*time.Second)
fmt.Println("Let’s hope the news will published before I leave.")
// Wait for the news to be published.
time.Sleep(10 * time.Second)
fmt.Println("Ten seconds later: I’m leaving now.")
}
该程序很可能以给定的顺序打印以下三行,每行之间有五秒钟的间隔。
$ go run publish1.go
Let’s hope the news will published before I leave.
BREAKING NEWS: A goroutine starts a new thread.
Ten seconds later: I’m leaving now.
通常,不可能通过sleep来安排线程等待彼此。 Go的主要同步方法是使用channels。
Goroutines是轻量级的。会导致较小的栈增长,主要通过根据需要分配和释放堆存储。内部goroutines就像在多个操作系统线程之间复用的协程一样。如果一个goroutine被阻塞,例如等待输入,则此线程中的其他goroutine将迁移,以便它们可以继续运行。
2、channels的同步通信
channel是goroutine通过传递值来同步执行和通信的机制。
// unbuffered channel of ints
ic := make(chan int)
// buffered channel with room for 10 strings
sc := make(chan string, 10)
要在channel上发送值,请使用<-作为二元运算符。要在channel上接收值,请将其用作一元运算符。
ic <- 3 // Send 3 on the channel.
n := <-sc // Receive a string from the channel.
<- 运算符指定channel方向,发送或接收。如果没有给出方向,则通道是双向的。
chan Sushi // can be used to send and receive values of type Sushi
chan<- string // can only be used to send strings
<-chan int // can only be used to receive ints
缓冲和无缓冲channel
- 如果channel的容量为零或不存在,则channel是无缓冲的,发送方将阻塞,直到接收方收到该值。
- 如果channel有缓冲区,则发送方仅阻塞,直到将值复制到缓冲区为止; 如果缓冲区已满,则表示等待某个接收方检索到某个值。
- 接收方始终阻塞,直到有数据要接收。
- 从nil channel发送或接收将永久阻塞。
关闭channel
close函数调用后标志将不再在channel上发送值。请注意,只有在接收方期望关闭时才需要关闭channel。
1. 在调用close之后,在收到任何先前发送的值之后,接收操作将返回零值而不会阻塞。
2. 多值接收操作另外返回channel是否关闭的标识。
3. 发送或关闭已关闭的channel会导致运行时出现panic。关闭nil channel也会导致运行时panic。
ch := make(chan string)
go func() {
ch <- "Hello!"
close(ch)
}()
fmt.Println(<-ch) // Print "Hello!".
fmt.Println(<-ch) // Print the zero value "" without blocking.
fmt.Println(<-ch) // Once again print "".
v, ok := <-ch // v is "", ok is false.
// Receive values from ch until closed.
for v := range ch {
fmt.Println(v) // Will not be executed.
}
在下面的示例中,我们让Publish函数返回一个channel,该channel用于在文本发布时广播消息。
// Publish prints text to stdout after the given time has expired.
// It closes the wait channel when the text has been published.
func Publish(text string, delay time.Duration) (wait <-chan struct{}) {
ch := make(chan struct{})
go func() {
time.Sleep(delay)
fmt.Println(text)
close(ch)
}()
return ch
}
请注意,我们使用空结构channel来指示channel仅用于通信,而不是用于传递数据。 下面是使用该函数例子。
wait := Publish("important news", 2 * time.Minute)
// Do some more work.
<-wait // Block until the text has been published.
go基础之并发的更多相关文章
- Java基础】并发 - 多线程
Java基础]并发 - 多线程 分类: Java2014-05-03 23:56 275人阅读 评论(0) 收藏 举报 Java 目录(?)[+] 介绍 Java多线程 多线程任务执行 大多数 ...
- GO学习-(18) Go语言基础之并发
Go语言基础之并发 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微 ...
- 周末班:Python基础之并发编程
进程 相关概念 进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本 ...
- 网络基础之 并发编程之进程,多路复用,multiprocess模块
并发 1. 背景知识 2. 什么是进程 3. 进程调度 4. 并发与并行 5 同步\异步\阻塞\非阻塞(重点) 6.multiprocess模块 7.僵尸进程与孤儿进程 1.背景知识 一操作系统的作用 ...
- 【Java_基础】并发、并行、同步、异步、多线程的区别
1. 并发:位于同一个处理器上的多个已开启未完成的线程,在任意一时刻系统调度只能让一个线程获得CPU资源运行,虽然这种调度机制有多种形式(大多数是以时间片轮巡为主).但无论如何,都是通过不断切换需要运 ...
- Go语言基础之并发
并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天) ...
- GO_11:GO语言基础之并发concurrency
并发Concurrency 很多人都是冲着 Go 大肆宣扬的高并发而忍不住跃跃欲试,但其实从源码的解析来看,goroutine 只是由官方实现的超级“线程池”而已.不过话说回来,每个实例 4-5KB的 ...
- GO语言基础之并发concurrency
并发Concurrency 很多人都是冲着 Go 大肆宣扬的高并发而忍不住跃跃欲试,但其实从源码的解析来看,goroutine 只是由官方实现的超级“线程池”而已.不过话说回来,每个实例 4-5KB的 ...
- golang基础--Gocurrency并发
Go并发特点 goroutine只是由官方实现的超级"线程池"而已,每个实例4-5kb的栈内存占用和用于实现机制而大幅减少的创建和销毁开销. 并发不是并行(多CPU): Concu ...
- Python基础-week08 并发编程
一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...
随机推荐
- .net core 对象序列化为Json及Json反序列化关于DataContractJsonSerializer和Newtonsoft使用的完整案例,源码已更新至开源模板
很多人告诉你怎么用,但是却不会告诉你用什么好.不知道在进行序列化和反序列化Json时用那个好,因为有太多选择,如.NET Framework下可以选DataContractJsonSerializer ...
- What's your name?
Hello. My name is james. What's your name? Hi, I'm Jessica. Nice to meet you. Nice to meet you, too. ...
- 品优购(IDEA版)-第二天
品优购-第2天 学习目标 目标1:运用AngularJS前端框架的常用指令 目标2:完成品牌管理的列表功能 目标3:完成品牌管理的分页列表功能 目标4:完成品牌管理的增加功能 目标5:完成品牌管理的修 ...
- H5+app,自动更新后自动删除安装包
H5+app 自动删除安装包 一.前言 之前做好的app自动更新,遗留下了一个问题,就是自动更新后安装包没有自行删除掉. 好像现在的手机的系统是有安装完自动清理安装包的.想我这个H5+的app安装完后 ...
- C++中对C的扩展学习新增语法——lambda 表达式(匿名函数)
1.匿名函数基础语法.调用.保存 1.auto lambda类型 2.函数指针来保存注意点:[]只能为空,不能写东西 3.std::function来保存 2.匿名函数捕捉外部变量(值方式.引用方式) ...
- java编程思想第四版第三章要点习题
使用"简短的" 和正常的 打印语句来编写一个程序 package net.mindview.util; public class Print { /** * 不带有回车 * @pa ...
- Redis 工具 redis-port 使用
redis-port 是一个 Redis 工具,通过解析 rdb 文件,实现 Redis 主节点和从节点的数据同步. 摘要: 一个可以将redis主从集群,cluster上的数据实时迁移到 cod ...
- deepin MySQL 安装以及编码格式的修改utf-8
deepin MySQL 安装以及编码格式的修改utf-8: 1.sudo apt-get install mysql-server mysql-client 2.sudo mysql -u root ...
- docker入门篇
在网上的教程中,大多数是建议利用linux来安装docker,在此我也建议大家用linux安装,为什么?请看下图 docker使用go语言开发,并且运行在linux系统下,而如果想用window运行, ...
- drf序列化组件之视图家族
一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 两大视图类:APIVi ...