1. 程式人生 > 其它 >同步阻塞/同步非阻塞、非同步阻塞/非同步非阻塞

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

同步阻塞/非阻塞,非同步阻塞/非阻塞

宣告:本篇思想非原創,系從老師處聽來。因為CSDN發轉載需要有原文連結,本篇沒有原文連結,所以填的原創。

舉個栗子

1、你在家做飯,用普通的湯鍋,米放進去,就站在鍋邊,傻等飯熟。——這叫同步阻塞

單任務按順序執行。

是不是覺得浪費了大量的時間,於是你想提高時間的利用效率。

2、還是用普通的湯鍋,米放進去,然後繼續回去打遊戲,過一會就來看一次。——這叫同步非阻塞

多工,定時檢視任務執行狀態。

時間的利用率稍微提升了一點點,還有沒有辦法再提升一點呢?

3、你去某寶淘了個電飯鍋,飯熟了會自動跳閘的那種。米放進去,然後傻傻的看它怎麼做飯的。——這叫非同步阻塞

單任務,自動提交任務執行狀態。

這有什麼意義呢?完全沒利用好電飯鍋的優勢啊

4、這回學聰明瞭,米放進去,按下按鈕,然後就去打遊戲了,等到跳閘的時候就去吃飯 。——這叫非同步非阻塞

多工,自動提交任務執行狀態,合理分配,最大化利用資源。

這樣是不是聰明瞭很多,時間的利用率大大提升。

相對於程式而言的 ,非同步可以給你節省出更多的時間,讓你去幹別的事,同步只能由你自己主動去檢視。
孰優孰劣不言而喻 。

阻塞和非阻塞,也很好理解。

同步阻塞,順序執行,只能傻等,效率低下 。

同步非阻塞,稍微高明點,但是麻煩了很多,多做很多無用功。

非同步阻塞,這個等於自斷一臂,沒啥大意義。

非同步非阻塞,這才是非同步的最佳用法。

一、同步與非同步

同步與非同步關注的是訊息通訊機制(synchronous communication/ asynchronous communication)。所謂同步,就是在發出一個呼叫時,在沒有得到結果之前,該呼叫就不反回。但是一旦呼叫返回,就得到返回值了。換句話說,就是由呼叫者主動等待這個呼叫的結果。

而非同步則是相反,呼叫在發出之後,這個呼叫就直接返回了,所以就沒有返回結果。換句話說,當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在呼叫發出之後,被呼叫者通過“狀態”、“通知”、“回撥”三種途徑通知呼叫者。

可以使用哪一種途徑依賴於被帶呼叫者的實現,除非被呼叫者提供多種選擇,否則不受呼叫者控制。如果被呼叫者用狀態來通知,那麼呼叫者就需要每隔一定時間檢查一次,效率就很低。如果使用通知和回撥的方式,效率則很高。因為被呼叫者幾乎不需要做額外的操作。

舉個例子:

你打電話問書店老闆有沒有《分散式系統》這本書,如果是同步通訊機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。

而非同步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。

二、回撥函式

上面提到,回撥是非同步呼叫的一種實現方式。那麼什麼是回撥函式呢?

  • 概念

回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。

  • 舉個例子

概念不是太好理解,我們舉個例子。

沿用上面買書的例子,你的電話號碼就叫回撥函式,你把電話留給書店老闆就叫登記回撥函式,書店老闆查好了叫做觸發了回撥關聯的事件,老闆給你打電話叫做呼叫回撥函式。你接電話叫做響應回撥事件。

  • 程式碼實現(僅為了說明回撥函式)
# coding=utf-8
import time


def call_back():             # 回撥函式
    print "我是回撥函式"


def call_later(call_time, callback):
    # 沉睡call_time後,呼叫回撥函式
    time.sleep(call_time)       
    callback()

if __name__ == '__main__':
    call_later(10, call_back)   # 登記回撥函式

三、阻塞與非阻塞

阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態。

阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒。

接著上面的例子:

你打電話問書店老闆有沒有《分散式系統》這本書,你如果是阻塞式呼叫,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式呼叫,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。

四、故事描述

老張愛喝茶,廢話不說,煮開水。

出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。

  1. 老張把水壺放到火上,立等水開。(同步阻塞)老張覺得自己有點傻。
  2. 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)。
  3. 老張還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嘀~~~~的噪音。
  4. 老張把響水壺放到火上,立等水開。(非同步阻塞)。
  5. 老張覺得這樣傻等意義不大,老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(非同步非阻塞)。
  • 所謂同步非同步,只是對於水壺而言。普通水壺,同步;響水壺,非同步。雖然都能幹活,但響水壺可以在自己完工之後,提示老張水開了。這是普通水壺所不能及的。同步只能讓呼叫者去輪詢自己(情況2中),造成老張效率的低下。
  • 所謂阻塞非阻塞,僅僅對於老張而言。立等的老張,阻塞;看電視的老張,非阻塞。
    情況1和情況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是非同步的,可對於立等的老張沒有太大的意義。所以一般非同步是配合非阻塞使用的,這樣才能發揮非同步的效用。