面試官:瞭解鎖麼?
小王:我X,這個問題不難呀!Lock、ReadWriteLock、Synchronized都在專案中使用過。
面試官:那有沒有比Lock、ReadWriteLock、Synchronized鎖更快的鎖呢?
小王:這這。。。。。。沉思好久。。。。。。問地好深呀,真不知道。
因為在專案中小王使用最多的就是這三種鎖,這個面試讓他知道了還有比鎖更快的鎖。
避免鎖:讀-複製-更新(RCU)
最快的鎖是根本沒有鎖!!!
最快的鎖是根本沒有鎖!!!
最快的鎖是根本沒有鎖!!!
重要的話重複三遍。在沒有鎖的情況,我們是否允許對共享資料進行併發讀寫訪問。在通常情況下,答案是否定的。
假設記憶體中存放一個數組數字Array{1,5,6,7,8,9},程序A正在對該陣列數字進行排序,而程序B正在計算其平均值。因為A對陣列數值前後來回移動,所以B可能得到的不同的數值,得到的結果可能是任意值,結果幾乎肯定是錯誤的。然而,在某些情況下,我們可以允許寫操作來更新資料結構,即便還有其他的程序正在使用它。竅門在於確保每個讀操作要麼讀取舊的資料版本,要麼讀取新的資料版本,但絕不能是新舊資料的奇怪組合。
舉例說明:樹型資料結構(注:在樹中插入一個節點,然後移除一個分支,整個過程中不涉及鎖)
該樹型結構中,讀操作從根部到葉子遍歷整個樹。在圖的上半部分,加入一個新的節點X。為了實現這一操作,我們要讓這個節點在樹中可見之前使它”恰好正確“:我們對節點X中的所有值進行初始化,包括它的子節點指標。然後透過原子寫操作,使X成為A的子節點。所有的讀操作都不會讀到前後不一致的版本。在圖的下半部分,我們接著移除B和D。首先,將A的左子節點指標指向C。所有原本在A中的讀操作將會後續讀到節點C,而永遠不會讀B和D。也就是說。它們將只會讀到新版資料。同樣,所有原本在A中的讀操作將會後續讀到節點C,而永遠不會讀B和D。也就是說,它們將只會讀到新版資料。同樣。所有當前在B和D中的讀操作將繼續依照原始的資料結構指標並且讀取舊版資料。所有操作均正確進行,我們不需要鎖住任何東西。而不需要鎖住資料結構就能夠移去B和D的主要原因就是RCU,將更新過程中的移除和再分配過程分離開來。
總結
RCU的優點是既允許多個程序對共享資料進行的讀操作同時執行,又允許多個程序對共享資料進行讀操作和寫操作同時執行。