同步/异步和阻塞/非阻塞学习笔记
概述
看了几篇同步,异步,阻塞和非阻塞的文章,感觉还是云里雾里的。本文结合自己的理解写几个例子加深印象,可能理解有误。大佬们可以帮忙批评指正。
个人理解同步/异步,阻塞/非阻塞是站在不同角度看的概念。
同步/异步:站在被调用方视角看,同步会执行调用方的请求,请求结束后返回执行结果给调用方。异步会先响应调用方请求,在执行调用方请求,最后给结果。
阻塞/非阻塞:站在调用方视角看,阻塞会等待被调用方响应,在等待期间啥事也不干。非阻塞在等待被调用方响应期间可以干别的事。
示例
本文以买咖啡为例介绍同步,异步,阻塞和非阻塞的几种情况。
同步阻塞
type Customer struct{}
func (c *Customer) BuyCoffee() {
coffee, ok := worker.MakeCoffee()
if !ok {
fmt.Println("make coffee failed")
}
fmt.Println("get my coffee", coffee.Name)
}
type Coffee struct {
Name string
}
type Worker struct{}
var worker Worker
func (w *Worker) MakeCoffee() (coffee *Coffee, ok bool) {
fmt.Println("start make coffee")
time.Sleep(1 * time.Second)
fmt.Println("make coffee finish")
return &Coffee{Name: "latte"}, true
}
func main() {
hxia := &Customer{}
hxia.BuyCoffee()
}
同步阻塞,当用户买咖啡时,咖啡师开始做用户的这一杯咖啡,用户等咖啡做好。咖啡师做好后把咖啡给用户,用户拿到咖啡。这是同步逻辑,可以看到同步阻塞,当咖啡师做咖啡时,用户啥也不干,效率较低。
异步阻塞
type Customer struct{}
func (c *Customer) BuyCoffee() {
go worker.MakeCoffee()
for coffeeWithResult := range coffeec {
if !coffeeWithResult.Result {
fmt.Println("make coffee failed")
}
if coffeeWithResult.Coffee != nil {
fmt.Println("get my coffee", coffeeWithResult.Coffee.Name)
}
}
}
type Coffee struct {
Name string
}
type Worker struct{}
var worker Worker
func (w *Worker) Do() {
fmt.Println("start make coffee")
time.Sleep(1 * time.Second)
fmt.Println("make coffee finish")
}
type CoffeeWithResult struct {
Coffee *Coffee
Result bool
}
var coffeec = make(chan CoffeeWithResult)
func (w *Worker) MakeCoffee() {
fmt.Println("response to customer that I'm start to make your coffee")
coffeec <- CoffeeWithResult{Coffee: nil, Result: true}
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
w.Do()
}()
wg.Wait()
coffeec <- CoffeeWithResult{Coffee: &Coffee{Name: "latte"}, Result: true}
close(coffeec)
}
func main() {
hxia := &Customer{}
hxia.BuyCoffee()
}
异步阻塞,当用户买咖啡时,咖啡师先告诉用户我在做咖啡了,用户还是等咖啡做好。咖啡师告诉用户之后,才继续做咖啡。异步对咖啡师友好,如果咖啡师在做咖啡的间隙还能做别的,咖啡师可以去做别的事情(咖啡师可以同时做好几杯咖啡,而不是用户这一杯)。对于咖啡师来说效率提高了。
同步非阻塞
type Customer struct{}
func (c *Customer) BuyCoffee() {
go worker.MakeCoffee()
for {
select {
case CoffeeWithResult, ok := <-coffeec:
if !ok {
return
}
if !CoffeeWithResult.Result {
fmt.Println("make my coffee failed")
break
}
if CoffeeWithResult.Coffee != nil {
fmt.Println("get my coffee", CoffeeWithResult.Coffee.Name)
}
default:
fmt.Println("do something")
time.Sleep(100 * time.Millisecond)
}
}
}
type Coffee struct {
Name string
}
type Worker struct{}
var worker Worker
type CoffeeWithResult struct {
Coffee *Coffee
Result bool
}
var coffeec = make(chan CoffeeWithResult)
func (w *Worker) MakeCoffee() {
fmt.Println("start make coffee")
time.Sleep(1 * time.Second)
fmt.Println("make coffee finish")
coffeec <- CoffeeWithResult{Coffee: &Coffee{Name: "latte"}, Result: true}
close(coffeec)
}
func main() {
hxia := &Customer{}
hxia.BuyCoffee()
}
同步非阻塞,当用户买咖啡时,咖啡师开始做这一杯咖啡,用户在等咖啡期间可以做别的事情(玩玩手机,回复信息等等)。咖啡师做好咖啡后告诉用户,用户再去取咖啡。对于用户来说效率提高了,不是在那干等。
异步非阻塞
type Customer struct{}
func (c *Customer) BuyCoffee() {
go worker.MakeCoffee()
for {
select {
case CoffeeWithResult, ok := <-coffeec:
if !ok {
return
}
if !CoffeeWithResult.Result {
fmt.Println("make my coffee failed")
break
}
if CoffeeWithResult.Coffee != nil {
fmt.Println("get my coffee", CoffeeWithResult.Coffee.Name)
}
default:
fmt.Println("do something")
time.Sleep(100 * time.Millisecond)
}
}
}
type Coffee struct {
Name string
}
type Worker struct{}
var worker Worker
func (w *Worker) Do() {
fmt.Println("start make coffee")
time.Sleep(1 * time.Second)
fmt.Println("make coffee finish")
}
type CoffeeWithResult struct {
Coffee *Coffee
Result bool
}
var coffeec = make(chan CoffeeWithResult)
func (w *Worker) MakeCoffee() {
fmt.Println("response to customer that I'm start to make your coffee")
coffeec <- CoffeeWithResult{Coffee: nil, Result: true}
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
w.Do()
}()
wg.Wait()
coffeec <- CoffeeWithResult{Coffee: &Coffee{Name: "latte"}, Result: true}
close(coffeec)
}
func main() {
hxia := &Customer{}
hxia.BuyCoffee()
}
异步非阻塞,有了前面的介绍,我们应该知道,异步的话咖啡师可以并行做几杯咖啡,而不是只做用户这一杯,用户在等咖啡期间也可以干自己的事,而不是只等自己的咖啡。对于用户和咖啡师效率都提高了。
参考文章
芝兰生于空谷,不以无人而不芳。

浙公网安备 33010602011771号