鎖的來由和使用
對于開發系統級別軟件的朋友來說,無論你是主動的還是被動的,鎖的應用都是少不了的。很多人用鎖,可是卻未必知道鎖的前世今生,什么時候用鎖,什么時候不用鎖?該用什么樣的鎖?今天我們就來對這個問題說道說道。
(1)為什么用鎖?
之所以會用鎖,其根本目的在于對公共資源的保護。比如說,我們希望對某些數據的操作是連貫的、具體的。否則,如果這些臟數據如果被再次引用的話,肯定會引發不可預計的故障。雖然從代碼上看,我們的操作可能只是一條語句,但是它所對應的匯編操作很有可能是由幾條命令合在一起完成的,所以中間發生任何的切換、中斷都會出現問題。那么,有哪些變動會導致這種情況發生呢?其實也不復雜,主要就三種,
a)中斷
b)搶占
c)smp
(2)哪些場景需要互斥處理?
上面說了三種情形,其實就是代碼有可能被打擾的三種情況。首先,中斷的發生是隨機的,如果中斷中使用了和內核段同樣的數據,那么肯定會惹麻煩的。同樣,搶占也是一個很重要的問題。所謂的搶占,其實就是說線程在中斷返回、資源釋放、搶占點有可能被系統切換出運行隊列。有些時候,線程的數據可能需要與另外一個線程進行分享,如果我們此時不想和別人分享,那么關閉搶占就可以了,系統也不會進行線程調度處理了。最后一種是多cpu情形,本質上和多線程有關,不同的cpu運行不同的線程,所以對于數據的訪問必須是互斥的,我們必須利用硬件提供的匯編語句來對代碼進行互斥處理,自旋鎖就是用的最多的一種方法。
(3)有哪些鎖的使用方法?
為了提高數據的訪問效率,人們設計了各種各樣的鎖。所有這些設計的目的只有一個,就是在保持數據正確性的條件下盡可能將鎖造成的影響降到最小。這從linux內核發展的軌跡可以清晰地看出來,越是高級的鎖,越是具有特定的應用場景,越需要小心處理。就我個人了解,當前使用較多的鎖主要有下面幾種:
a)關中斷
b)禁止搶占
c)自旋鎖
d)原子操作
e)讀寫鎖
f)互斥量
g)信號量
h)事件
(4)使用鎖需要注意些什么?
在所有代碼里面,關于多線程的編寫其實是很難的,主要是因為多線程考慮的情況多,另外一方面就是代碼調試的難度很大,所以在模塊設計的時候一定要慎重。在平時編寫的時候,多用成熟代碼,這樣才會在軟件質量上有所保障。不過,在鎖的使用中,還是有一些規則是要注意的,比如,
a)中斷的代碼是不能使用帶有schedule函數的鎖
b)搶占只能防止本cpu上線程之間的互斥
c)使用自旋鎖的代碼段不能太長,否則影響系統性能
d)互斥量只能被本線程釋放,在嵌入式實時系統中可能會遇到優先級反轉的問題
e)使用信號量最合適的地方就是pv操作
f)原子鎖計數比較合適
g)事件功能和網絡編程中的select很像,可以響應多個情形,但是無法保證這些事件有序
h)鎖成對使用、有序使用,做到這些可解決一大部分的死鎖問題
i)沒事別寫多線程,就是寫也先把單線程的代碼完善好了再進行考慮和移植
j)在鎖中使用指針需要十分小心
posted on 2012-08-01 10:49 順其自然EVO 閱讀(202) 評論(0) 編輯 收藏 所屬分類: 數據庫