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

    1. 如果channel的容量为零或不存在,则channel是无缓冲的,发送方将阻塞,直到接收方收到该值。
    2. 如果channel有缓冲区,则发送方仅阻塞,直到将值复制到缓冲区为止; 如果缓冲区已满,则表示等待某个接收方检索到某个值。
    3. 接收方始终阻塞,直到有数据要接收。
    4. 从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基础之并发的更多相关文章

  1. Java基础】并发 - 多线程

    Java基础]并发 - 多线程 分类: Java2014-05-03 23:56 275人阅读 评论(0) 收藏 举报 Java   目录(?)[+]   介绍 Java多线程 多线程任务执行 大多数 ...

  2. GO学习-(18) Go语言基础之并发

    Go语言基础之并发 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微 ...

  3. 周末班:Python基础之并发编程

    进程 相关概念 进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本 ...

  4. 网络基础之 并发编程之进程,多路复用,multiprocess模块

    并发 1. 背景知识 2. 什么是进程 3. 进程调度 4. 并发与并行 5 同步\异步\阻塞\非阻塞(重点) 6.multiprocess模块 7.僵尸进程与孤儿进程 1.背景知识 一操作系统的作用 ...

  5. 【Java_基础】并发、并行、同步、异步、多线程的区别

    1. 并发:位于同一个处理器上的多个已开启未完成的线程,在任意一时刻系统调度只能让一个线程获得CPU资源运行,虽然这种调度机制有多种形式(大多数是以时间片轮巡为主).但无论如何,都是通过不断切换需要运 ...

  6. Go语言基础之并发

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天) ...

  7. GO_11:GO语言基础之并发concurrency

    并发Concurrency 很多人都是冲着 Go 大肆宣扬的高并发而忍不住跃跃欲试,但其实从源码的解析来看,goroutine 只是由官方实现的超级“线程池”而已.不过话说回来,每个实例 4-5KB的 ...

  8. GO语言基础之并发concurrency

    并发Concurrency 很多人都是冲着 Go 大肆宣扬的高并发而忍不住跃跃欲试,但其实从源码的解析来看,goroutine 只是由官方实现的超级“线程池”而已.不过话说回来,每个实例 4-5KB的 ...

  9. golang基础--Gocurrency并发

    Go并发特点 goroutine只是由官方实现的超级"线程池"而已,每个实例4-5kb的栈内存占用和用于实现机制而大幅减少的创建和销毁开销. 并发不是并行(多CPU): Concu ...

  10. Python基础-week08 并发编程

    一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...

随机推荐

  1. .net core 对象序列化为Json及Json反序列化关于DataContractJsonSerializer和Newtonsoft使用的完整案例,源码已更新至开源模板

    很多人告诉你怎么用,但是却不会告诉你用什么好.不知道在进行序列化和反序列化Json时用那个好,因为有太多选择,如.NET Framework下可以选DataContractJsonSerializer ...

  2. 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. ...

  3. 品优购(IDEA版)-第二天

    品优购-第2天 学习目标 目标1:运用AngularJS前端框架的常用指令 目标2:完成品牌管理的列表功能 目标3:完成品牌管理的分页列表功能 目标4:完成品牌管理的增加功能 目标5:完成品牌管理的修 ...

  4. H5+app,自动更新后自动删除安装包

    H5+app 自动删除安装包 一.前言 之前做好的app自动更新,遗留下了一个问题,就是自动更新后安装包没有自行删除掉. 好像现在的手机的系统是有安装完自动清理安装包的.想我这个H5+的app安装完后 ...

  5. C++中对C的扩展学习新增语法——lambda 表达式(匿名函数)

    1.匿名函数基础语法.调用.保存 1.auto lambda类型 2.函数指针来保存注意点:[]只能为空,不能写东西 3.std::function来保存 2.匿名函数捕捉外部变量(值方式.引用方式) ...

  6. java编程思想第四版第三章要点习题

    使用"简短的" 和正常的 打印语句来编写一个程序 package net.mindview.util; public class Print { /** * 不带有回车 * @pa ...

  7. Redis 工具 redis-port 使用

    redis-port 是一个 Redis 工具,通过解析 rdb 文件,实现 Redis 主节点和从节点的数据同步.   摘要: 一个可以将redis主从集群,cluster上的数据实时迁移到 cod ...

  8. deepin MySQL 安装以及编码格式的修改utf-8

    deepin MySQL 安装以及编码格式的修改utf-8: 1.sudo apt-get install mysql-server mysql-client 2.sudo mysql -u root ...

  9. docker入门篇

    在网上的教程中,大多数是建议利用linux来安装docker,在此我也建议大家用linux安装,为什么?请看下图 docker使用go语言开发,并且运行在linux系统下,而如果想用window运行, ...

  10. drf序列化组件之视图家族

    一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 ​ 两大视图类:APIVi ...