1. 程式人生 > >同步和非同步、阻塞、髒讀和不可重複讀

同步和非同步、阻塞、髒讀和不可重複讀

1、同步和非同步的概念理解   同步和非同步通常用來形容一次方法呼叫。同步方法呼叫一旦開始,呼叫者必須等到方法呼叫返回後,才能繼續後續的行為。非同步方法呼叫更像一個訊息傳遞,一旦開始,方法呼叫就會立即返回,呼叫者就可以繼續後續的操作,而且非同步方法通常會在另外一個執行緒中,“真實”地執行著。整個過程,不會阻礙呼叫者的工作。

        簡而言之,言而總之:同步就是我強依賴你(對方),我必須等到你的回覆,才能做出下一步響應。即我的操作(行程)是順序執行的,中間少了哪一步都不可以,或者說中間哪一步出錯都不可以,類似於程式設計中程式被直譯器順序執行一樣;同時如果我沒有收到你的回覆,我就一直處於等待、也就是阻塞的狀態。 非同步則相反,我並不強依賴你,我對你響應的時間也不敏感,無論你返回還是不返回,我都能繼續執行;你響應並返回了,我就繼續做之前的事情,你沒有響應,我就做其他的事情。也就是說我不存在等待對方的概念,我就是非阻塞的。        從上面的例子來看:同步似乎等價於阻塞,非同步則等價於非阻塞。其實有些狹義,但不可否認的是,在一定情況下,確實可以這麼認為;因為同步一定存在著阻塞狀態,而非同步一定不存在非阻塞的狀態

。 但是不是就是說同步呼叫 == 阻塞呼叫呢?並不是;阻塞和非阻塞強調的是程式在等待呼叫結果(訊息,返回值)時的狀態.  阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒。

      對於同步呼叫來說,很多時候當前執行緒還是啟用的狀態,只是從邏輯上當前函式沒有返回而已,即同步等待時什麼都不幹,白白佔用著資源。同步和非同步強調的是訊息通訊機制 (synchronous communication/ asynchronous communication)。所謂同步,就是在發出一個"呼叫"時,在沒有得到結果之前,該“呼叫”就不返回。但是一旦呼叫返回,就得到返回值了。換句話說,就是由“呼叫者”主動等待這個“呼叫”的結果。而非同步則是相反,"呼叫"在發出之後,這個呼叫就直接返回了,所以沒有返回結果。換句話說,當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在"呼叫"發出後,"被呼叫者"通過狀態、通知來通知呼叫者,或通過回撥函式處理這個呼叫。

2、同步和非同步的區別聯絡

      同步:在執行完一個函式或方法後,一直等待系統返回值或訊息,這時程式是處於阻塞狀態的。只有接收到返回值或訊息後才往下執行其它命令。        非同步:執行完函式或方法後,不必阻塞性的等待返回值或訊息,只需要向系統委託一個非同步過程,當系統接收到返回值或訊息時,系統會自動觸發委託的非同步過程,從而完成一個完整的流程。        同步就是把事情一件一件的做,同一時間只能做一件事;非同步是做一件事情的時候可以同時做其它事情。

3、對阻塞的理解

      執行緒在執行中如果遇到磁碟讀寫或網路通訊(統稱為I/O 操作),通常要耗費較長的時間,這時作業系統會剝奪這個執行緒的CPU 控制權,使其暫停執行,同時將資源讓給其他的工作執行緒,這種執行緒排程方式稱為阻塞。當I/O 操作完畢時,作業系統將這個執行緒的阻塞狀態解除,恢復其對CPU的控制權,令其繼續執行

。這種I/O 模式就是通常的同步式I/O(Synchronous I/O)或阻塞式I/O (Blocking I/O)。相應地,非同步式I/O (Asynchronous I/O)或非阻塞式I/O (Non-blocking I/O)則針對所有I/O 操作不採用阻塞的策略。        當執行緒遇到I/O 操作時,不會以阻塞的方式等待I/O 操作的完成或資料的返回,而只是將I/O 請求傳送給作業系統,繼續執行下一條語句。當作業系統完成I/O 操作時,以事件的形式通知執行I/O 操作的執行緒,執行緒會在特定時候處理這個事件。為了處理非同步I/O,執行緒必須有事件迴圈,不斷地檢查有沒有未處理的事件,依次予以處理。阻塞模式下,一個執行緒只能處理一項任務,要想提高吞吐量必須通過多執行緒。因為一個執行緒阻塞時還有其他執行緒在工作,多執行緒可以讓CPU 資源不被阻塞中的執行緒浪費。而在非阻塞模式下,執行緒不會被I/O 阻塞,永遠在利用CPU。       多執行緒帶來的好處僅僅是在多核CPU 的情況下利用更多的核,而Node.js的單執行緒也能帶來同樣的好處。這就是為什麼Node.js 使用了單執行緒、非阻塞的事件程式設計模式。

4、髒資料和不可重複讀

       髒讀又稱無效資料的讀出,是指在資料庫訪問中,事務T1將某一值修改,然後事務T2讀取該值,此後T1因為某種原因撤銷對該值的修改,這就導致了T2所讀取到的資料是無效的。         通俗解釋:髒讀就是指當一個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外一個事務也訪問這個資料,然後使用了這個資料。因為這個資料是還沒有提交的資料,那麼另外一個事務讀到的這個資料是髒資料,依據髒資料所做的操作可能是不正確的。

      不可重複讀,是指在資料庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一資料,事務T2讀取並修改了該資料,T1為了對讀取值進行檢驗而再次讀取該資料,便得到了不同的結果。        通俗解釋:在一個事務內,多次讀同一個資料。在這個事務還沒有結束時,另一個事務也訪問該同一資料。那麼,在第一個事務的兩次讀資料之間。由於第二個事務的修改,那麼第一個事務讀到的資料可能不一樣,這樣就發生了在一個事務內兩次讀到的資料是不一樣的,因此稱為不可重複讀,即原始讀取不可重複。