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. OpenCV的Mat构造函数

    1.函数说明 构造函数:public Mat(int rows, int cols, MatType type, IntPtr data, long step = 0) 可以通过数据指针构造Mat对象 ...

  2. linux下 驱动模块编译步骤

    本文将直接了当的带你进入linux的模块编译.当然在介绍的过程当中,我也会添加一些必要的注释,以便初学者能够看懂.之所以要写这篇文章,主要是因为从书本上学的话,可能要花更长的时间才能学会整个过程,因为 ...

  3. 关于Python中的yield的理解

    生成器:yield表达式构成的函数就是生成器:每一个生成器都是一个迭代器(但是迭代器不一定是生成器).return就是迭代器: yield的功能类似于return,不同之处在于它返回的是生成器. 什么 ...

  4. 深入理解计算机系统 第八章 异常控制流 part1

    本章主旨 第八章的目的是阐述清楚应用程序是如何与操作系统交互的(之前章节的学习是阐述应用程序是如何与硬件交互的) 异常控制流 异常控制流,即 ECF(exceptional contril flow) ...

  5. [干货]AspNetCore熟练应用CancellationToken,CTO会对你刮目相看

    背景 已经有很多文章记录了 web程序中采用异步编程的优势和.Net异步编程的用法, 异步编程虽然不能解决查询数据库的瓶颈, 但是利用线程切换,能最大限度的弹性利用工作线程, 提高了web服务的响应能 ...

  6. [LC]643题 Maximum Average Subarray I(子数组最大平均数 I)

    ①英文题目 Given an array consisting of n integers, find the contiguous subarray of given length k that h ...

  7. Mssql 查询某记录前后N条

    Sqlserver 查询指定记录前后N条,包括当前数据 条件 [ID] 查询 [N]条 select * from [Table] where ID in (select top ([N]+1) ID ...

  8. flex一些属性

    // 改变主轴的方向 flex-direction: column; // display:flex的子元素无法设置宽度 // 子元素有个flex-shrink属性,表示在父元素宽度不够的情况下是否自 ...

  9. API的描述语言--Swagger

    Swagger是一种Rest API的表示方式. 有时也可以作为Rest API的交互式文档,描述形式化的接口描述,生成客户端和服务端的代码. 一,描述语言:Spec Swagger API Spec ...

  10. MyEclipse使用总结

    0.快捷键 ================================================================================ 编辑: Ctrl+Shif ...