同步 / 异步、阻塞 / 非阻塞


前言

同步异步,在计算机科学中是一个非常重要的概念。作为一位软件开发工程师,我们每天都在和同步和异步打交道。

同步

同步-阻塞(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获取结果
异步-非阻塞 异步执行 回调

文章作者: 徐镖林
WeChat QR Code
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 徐镖林 !
  目录