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. 你了解MySQL的加锁规则吗?

    注:加锁规则指的是next-key lock,如果还不了解next-key lock,请阅读上一篇博客 加锁规则可以概括为:两个原则.两个优化和一个bug: 原则1:加锁的基本单位是next-key ...

  2. WIN7安装Docker Toolbox、制作镜像并发到阿里云

    一.安装Docker Toolbox,并配置国内源加速 WIndows7不支持Hyper-v,所以只能采用Docker Toolbox的方式使用Docker.传送门:http://mirrors.al ...

  3. 瞎折腾实录:构建 Armel 版本的 .NET Core 教程和资料资源

    目录 首先我要说明,我失败了~ 我把我的进度和经验放出来,希望能够帮助别人完成编译工作~ 背景:最近接手一个华为某型号的嵌入式设备,需要在上面搭建 .NET Core 环境. 设备是 Armel 架构 ...

  4. Centos 7.X 安装及常规设置

    一.制作USBHDD+启动 需要工具: UltraISO(软碟通) U盘 centos7镜像: http://www.centos.org 二.安装(有坑) U盘启动电脑,进入安装界面: 选中第一项, ...

  5. 【原创】使用批处理脚本生成包并自动上传到nuget

    Hello 大家好,我是TANZAME,我们又见面了. NuGet 是什么这里就不再重复啰嗦,园子里一搜一大把.今天要跟大家分享的是,在日常开发过程中如何统一管理我们的包,如何通过批处理脚本生成包并自 ...

  6. PHP 发送get请求

    PHP 发送get请求 file_get_contents 方法: $s = file_get_contents("http://apis.map.qq.com/ws/distance/v1 ...

  7. gopls替换hover文档

    一直在用vscode来开发golang程序,也一直在用 gopls语言服务器,也一直用鼠标悬浮显示函数的文档. 今天 偶然关闭了 gopls,然后 鼠标悬浮后,发现了 新大陆,nima,gopls的 ...

  8. NetCore3.0 文件上传与大文件上传的限制

    NetCore文件上传两种方式 NetCore官方给出的两种文件上传方式分别为“缓冲”.“流式”.我简单的说说两种的区别, 1.缓冲:通过模型绑定先把整个文件保存到内存,然后我们通过IFormFile ...

  9. C语言|博客作业02

    这个作业属于哪个课程 C程序语言设计 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-1/homework/8654 我在这个课程的目标是 ...

  10. SIGCHLD waitpid, 小心子进程结束事件被偷了

    原本项目中依赖子进程执行的地方,都使用jni调用java层的ProcessManager,换了c++ACE框架后,发现这些任务都很慢,调试才发现所有子进程执行的任务都必须等待到reactor超时才返回 ...