内容简介:Java 中有一系列的线程同步的方法,go 里面有 goroutine(协程),先看下下面的代码执行的结果是什么呢?执行以上代码很可能看不到输出。
前言
Java 中有一系列的线程同步的方法,go 里面有 goroutine(协程),先看下下面的代码执行的结果是什么呢?
package main
import (
"fmt"
)
func main() {
go func() {
fmt.Println("Goroutine 1")
}()
go func() {
fmt.Println("Goroutine 2")
}()
}
执行以上代码很可能看不到输出。
因为有可能这两个协程还没得到执行,主协程就已经结束了,而主协程结束时会结束所有其他协程,所以导致代码运行的结果什么都没有。
估计不少新接触 go 的童鞋都会对此郁闷:unamused:,可能会问那么该如何等待主协程中创建的协程执行完毕之后再结束主协程呢?
下面说几种可以解决的方法:
Sleep 一段时间
在 main 方法退出之前 sleep 一段时间就 可能 会出现结果了,如下代码:
package main
import (
"fmt"
"time"
)
func main() {
go func() {
fmt.Println("Goroutine 1")
}()
go func() {
fmt.Println("Goroutine 2")
}()
time.Sleep(time.Second * 1) // 睡眠1秒,等待上面两个协程结束
}
这两个简单的协程执行消耗的时间很短的,所以你会发现现在就有结果出现了。
Goroutine 1 Goroutine 2
为什么上面我要说 “可能会出现” ?
因为 sleep 这个时间目前是设置的 1s,如果我这两个协程里面执行了很复杂的逻辑操作(时间大于 1s),那么就会发现依旧也是无结果打印出来的。
那么就可以发现这种方式得到问题所在了: 我们无法确定需要睡眠多久
上面那种方式有问题,go 里面其实也可以用管道来实现同步的。
管道实现同步
那么用管道怎么实现同步呢?show code:
package main
import (
"fmt"
)
func main() {
ch := make(chan struct{})
count := 2 // count 表示活动的协程个数
go func() {
fmt.Println("Goroutine 1")
ch <- struct{}{} // 协程结束,发出信号
}()
go func() {
fmt.Println("Goroutine 2")
ch <- struct{}{} // 协程结束,发出信号
}()
for range ch {
// 每次从ch中接收数据,表明一个活动的协程结束
count--
// 当所有活动的协程都结束时,关闭管道
if count == 0 {
close(ch)
}
}
}
这种方式是一种比较完美的解决方案, goroutine / channel 它们也是在 go 里面经常搭配在一起的一对。
sync.WaitGroup
其实 go 里面也提供了更简单的方式 —— 使用 sync.WaitGroup。
WaitGroup 顾名思义,就是用来等待一组操作完成的。WaitGroup 内部实现了一个计数器,用来记录未完成的操作个数,它提供了三个方法:
- Add() 用来添加计数
- Done() 用来在操作结束时调用,使计数减一
- Wait() 用来等待所有的操作结束,即计数变为 0,该函数会在计数不为 0 时等待,在计数为 0 时立即返回
继续 show code:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2) // 因为有两个动作,所以增加2个计数
go func() {
fmt.Println("Goroutine 1")
wg.Done() // 操作完成,减少一个计数
}()
go func() {
fmt.Println("Goroutine 2")
wg.Done() // 操作完成,减少一个计数
}()
wg.Wait() // 等待,直到计数为0
}
你会发现也是可以看到运行结果的,是不是发现这种方式是很简单的。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java 并发编程:多线程并发访问,同步控制
- Java 并发编程:多线程并发访问,同步控制
- 深入Linux并发同步
- Golang 并发编程与同步原语
- 多线程六 同步容器&并发容器
- 浅谈 Golang 中数据的并发同步问题(三)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java5.0Tiger程序高手秘笈
BrettMclaughlin / 东南大学出版社 / 2005-10 / 28.00元
代号为 “Tiger”的下一个 Java 版本,不只是个小改动版。在语言核心中有超过 100 项以上的变动,同时有大量的对 library 与 API 所做的加强,让开发者取得许多新的功能、工具与技术。但在如此多的变化下,应该从何处开始着手?也许可以从既长又无趣的语言规范说明书开始看起;或等待最少 500 页的概念与理论巨著出版;甚至还可以直接把玩新的 JDK 看看能够有什么发现;或者借由《Jav......一起来看看 《Java5.0Tiger程序高手秘笈》 这本书的介绍吧!