深入理解無(wú)鎖編程
我學(xué)習(xí)無(wú)鎖編程是Bruce Dawson 出色而全面的白皮書Lockless Programming Considerations(無(wú)鎖編程的思考)。和許多技術(shù)一樣,需要將理論付諸實(shí)踐,在平臺(tái)上開(kāi)發(fā)和調(diào)試無(wú)鎖代碼。在這篇文章中,我想重新介紹無(wú)鎖編程,首先是定義它,然后將大部分信息提煉為幾個(gè)關(guān)鍵概念。我將使用流程圖展示這些概念如何相互關(guān)聯(lián),然后我們將深入研究細(xì)節(jié)。至少,任何從事無(wú)鎖編程的程序員都應(yīng)該已經(jīng)了解如何使用互斥鎖和其他高級(jí)同步對(duì)象(如信號(hào)量和事件)編寫正確的多線程代碼。它是什么?人們通常將無(wú)鎖編程描述為沒(méi)有互斥鎖的編程,互斥鎖也稱為鎖。這是真的,但這只是故事的一部分。基于學(xué)術(shù)文獻(xiàn)的普遍接受的定義更廣泛一些。從本質(zhì)上講,無(wú)鎖是一種用于描述某些代碼的屬性,而無(wú)需過(guò)多說(shuō)明該代碼的實(shí)際編寫方式。基本上,如果您的程序的某些部分滿足以下條件,那么該部分可以理所當(dāng)然地被認(rèn)為是無(wú)鎖的。相反,如果代碼的給定部分不滿足這些條件,則該部分不是無(wú)鎖的。
從這個(gè)意義上說(shuō),無(wú)鎖中的鎖并不直接指互斥鎖,而是指以某種方式“鎖定”整個(gè)應(yīng)用程序的可能性,無(wú)論是死鎖、活鎖——甚至是由于由你最大的敵人。最后一點(diǎn)聽(tīng)起來(lái)很有趣,但這是關(guān)鍵。共享互斥鎖被簡(jiǎn)單地排除在外,因?yàn)橐坏┮粋€(gè)線程獲得互斥鎖,您最大的敵人就再也不會(huì)調(diào)度該線程了。當(dāng)然,真正的操作系統(tǒng)不是這樣工作的——我們只是定義術(shù)語(yǔ)。
這是一個(gè)不包含互斥鎖但仍然不是無(wú)鎖的操作的簡(jiǎn)單示例。最初,X = 0。作為讀者的練習(xí),考慮如何以一種方式調(diào)度兩個(gè)線程,使得兩個(gè)線程都不退出循環(huán)。while(X == 0 ) {
X = 1 - X;
}
沒(méi)有人期望大型應(yīng)用程序是完全無(wú)鎖的。通常,我們從整個(gè)代碼庫(kù)中識(shí)別出一組特定的無(wú)鎖操作。例如,在一個(gè)無(wú)鎖隊(duì)列中,有可能是無(wú)鎖的操作,比如極少數(shù)的
push
,pop
也許isEmpty
等。Herlihy