在java高併發程式設計,有幾個很重要的內容:
1.CAS演算法
2.CPU重排序
3.快取行偽共享
我們先來說說高併發世界中的主要關鍵問題是什麼?
是資料共享。
因為多執行緒之間要共享資料,就會遇到各種問題。如下圖:
如果兩個執行緒同時寫入,那怎麼保證資料的一致性?是執行緒1先寫,還是執行緒2先寫,這是個問題。那要如何解決這個問題?
答案是:加鎖。
比如,執行緒1先訪問共享資料區,那麼它就先把這塊資料區鎖起來。後面如果其他執行緒要訪問這個共享區,首先要從執行緒1這裡獲取鎖,才能進一步訪問這個共享區。這裡很好理解,
其實相當於這樣的情景,你有一個抽屜,抽屜有把鎖,這個鎖的鑰匙,在你手上,你就可以開啟抽屜,往裡面存放或拿取物件。其他人,要從這個抽屜裡存放東西,必須徵得你的同意,從你手上拿到鑰匙,然後,他才能用這把鑰匙開啟抽屜,進行存放物件的動作。如下圖:
回到高併發的執行緒世界,我們知道,可以用加鎖來解決多執行緒訪問共享資料區的問題。那問題又來了,那這把鎖,先交給誰呢?怎麼解決這個問題呢?
答案是:鎖競爭。
多執行緒,如果在優先順序一樣的情況下,大家進行公平競爭?那怎麼樣才算公平競爭呢?一般情況下,我們都可以想到:先到先得。
是的,一般情況下,作業系統對執行緒競爭,都取用這個方式,這樣也符合常理。
好,執行緒1來了,獲得一把鎖,對這個共享資料區進行鎖定訪問。那別的執行緒,只能等待這個執行緒“辦完事”後,釋放鎖。這時,這些別的執行緒就進入等待狀態。
現在問題,又來了,如果執行緒1只是對這個共享資料區進行讀訪問,是否有必要把這個資料區全面鎖,不讓其他執行緒進行讀訪問呢?
沒有必要!
怎麼解決?
讀寫分離!
分別定義兩把鎖,一把讀鎖,一把寫鎖。寫鎖,還是對寫有獨佔權。讀鎖,就可以無限量地分發給其他多個執行緒。這樣不影響共享資料區的資料一致性。
其實,讀寫分離,是架構設計和資料庫設計中一個很重要的設計思想,也是高效能的一種設計理念。
好了,今天,我們主要講多執行緒高併發程式設計的核心概念:執行緒鎖。
明天,我們繼續講鎖的底層實現原理。