在使用共享內存的應用程序中,程序員必須特別留意保護共享資源,防止共享資源併發訪問。程序員
所謂臨界區就是訪問和操做共享數據代碼段。多個執行線程併發訪問同一個資源一般是不安全的,爲了不在臨界區中併發訪問,編程者必須保證這些代碼原子地執行。編程
若是兩個執行線程有可能處於同一個臨界區中同時執行,若是這種狀況確實發生了,咱們就稱它是競爭條件。由於競爭引發的錯誤很是不易重現,因此調試這種錯誤纔會很是困難。安全
避免併發和防止競爭條件稱爲同步。數據結構
爲何要保護?併發
有些事務必須完整地發生,要麼乾脆不發生,可是毫不能打斷。異步
鎖提供的就是這種機制:它就如同一把門鎖,門後的房間可想象成要給臨界區。在一個指定的時間內,房間裏只能有一個執行線程存在,當一個線程進入房間後,它會鎖住身後的房門。當它結束對共享數據的操做後,就會走出房間,打開門鎖。若是另外一個線程在房門上鎖時來了,那麼它就必須等待房間內的線程出來併發開門鎖後,才能進入房間。函數
線程持有鎖,鎖保護了數據。工具
內核中有相似可能形成併發執行的緣由,它們是:線程
真正困難的就是發現上述的潛在併發執行的可能,並有意識地採起某些措施來防止併發執行。設計
其實,真正用鎖來保護共享資源並不困難,尤爲是在設計代碼的早期就這麼作了,事情就更簡單了。
辨認出真正須要共享的數據和響應的臨界區,纔是真正有挑戰性的地方。
找出哪些數據須要保護是關鍵所在。
線程中的局部數據僅僅被它訪問,顯然不須要保護。還有動態分配的數據結構,其地址在堆棧中。也不須要
大多數內核數據結構都須要加鎖,
若是有其餘執行線程能夠訪問這些數據,那麼就給這些數據加上某種形式的鎖。
若是任何其餘什麼東西都能看到它,那麼就要鎖住它。記住:要給數據而不是給代碼加鎖。
在編寫代碼時,你要問本身下面這些問題:
簡而言之,全部內核全局變量和共享數據都須要某種形式的同步方法。
死鎖產生須要必定條件:要有一個或多個執行線程和一個或多個資源,每一個線程都在等待其中的一個資源,但全部資源都已經被佔用了。
自死鎖:一個執行線程試圖去得到要給本身已經持有的鎖,它將不得不等待鎖被釋放。最後智能死鎖
一些簡單的規則對避免死鎖大有幫助:
防止死鎖很重要,內核提供了一些簡單易用的調試工具,能夠在運行時檢測死鎖。
鎖的爭用,簡稱爭用,指當鎖正在被佔用時,有其餘線程試圖得到該鎖。
當一個鎖處於高度爭用狀態,會成爲系統的瓶頸。儘管如此,也比多個進程搶奪資源要好。
鎖的粒度,須要合理的安排。不少鎖的設計在開始階段都很粗,可是當鎖爭用問題嚴重時,設計就向更加精細的加鎖方向進化。