前言
同步异步,在计算机科学中是一个非常重要的概念。作为一位软件开发工程师,我们每天都在和同步和异步打交道。
同步
同步-阻塞(Sync-Blocking)
同步-阻塞,顾名思义,就是同步和阻塞。调用方法后,必须等到结果返回,才能继续执行别的任务。
现实生活类比:打电话,必须等到对方接听电话,才能继续说话。
代码实例:
package main
import ( "fmt" "time" )
func main() { fmt.Println("开始执行同步阻塞任务...") // 模拟一个耗时的同步操作 time.Sleep(2 * time.Second) fmt.Println("同步任务执行完成") // 在同步任务完成之前,这里的代码不会执行 fmt.Println("继续执行后续操作") }
|
同步-非阻塞(Sync-NonBlocking)
同步-非阻塞,调用方法后,不等结果返回,继续执行别的任务。
需要不断轮询,直到结果返回。会占用CPU资源。
现实生活类比:每隔一段时间你去看下外卖到了没有。
代码实例:
package main
import ( "fmt" "time" )
func main() { fmt.Println("开始执行同步非阻塞任务...") done := false startTime := time.Now() // 模拟一个需要轮询检查的任务 for !done { // 检查任务是否完成 if time.Since(startTime) >= 2*time.Second { done = true continue } fmt.Println("轮询检查任务状态...") // 执行其他操作 fmt.Println("执行其他任务...") time.Sleep(500 * time.Millisecond) } fmt.Println("同步非阻塞任务执行完成") }
|
异步
异步-阻塞(Async-Blocking)
异步-阻塞,调用方法后,任务是异步的,但是调用者会阻塞等待结果返回。
现实生活类比:你你让你朋友(其它线程)去餐馆点外卖(异步任务),然后外卖员送餐上门。但你必须在家等着,不能去做其他事情。
代码实例:
package main
import ( "fmt" "time" )
func main() { // 创建一个通道 ch := make(chan string)
// 启动一个goroutine执行异步任务 go func() { // 模拟耗时操作 time.Sleep(2 * time.Second) ch <- "异步任务完成" }()
fmt.Println("等待异步任务完成...") // 主线程阻塞等待异步任务完成 result := <-ch fmt.Println(result) }
|
异步-非阻塞(Async-NonBlocking)
异步-非阻塞,调用方法后,不等结果返回,继续执行别的任务,任务完成后通过回调函数通知调用者。
现实生活类比:你点了外卖,你继续工作,外卖员送餐上门后,外卖员会给你打电话通知你。
代码实例:
package main
import ( "fmt" "time" )
func main() { // 启动一个goroutine执行异步任务 go func() { // 模拟耗时操作 time.Sleep(2 * time.Second) // 通过回调函数通知任务完成 callback("异步任务完成") }()
fmt.Println("继续执行其他任务...") // 让主线程等待一会,以便看到异步任务的结果 time.Sleep(3 * time.Second) }
func callback(result string) { fmt.Println(result) }
|
总结
类型 |
是否等待结果 |
是否可以做其他事情 |
调用方式 |
同步-阻塞 |
是 |
否 |
同步返回 |
同步-非阻塞 |
轮询 |
是,轮询期间可以做其他事情 |
主动轮询检查 |
异步-阻塞 |
异步执行 |
否 |
通过Future获取结果 |
异步-非阻塞 |
异步执行 |
是 |
回调 |