在cs架構中專案中,執行緒的使用就成了無可避免的。在使用執行緒時,執行緒安全如何處理,以及如何避免死鎖?要解決這些問題,那麼我們需要了解,什麼是執行緒安全,什麼是死鎖?
什麼是執行緒安全?
執行緒安全問題其實是指多個執行緒對於某個共享資源的訪問導致的原子性、可見性和有序性問的問題,而這些問題會導致共享資料存在乙個不可**性,使得程式在執行的過程中會出現一些超預期的結果
通俗來說就是多執行緒同時執行,如果每次執行的結果和單執行緒執行的結果一致,那麼就是執行緒安全的。
什麼是非執行緒安全?
如何避免執行緒不安全?
解決執行緒不安全的方式是增加同步鎖,這裡筆者用過的是lock鎖,由於導致執行緒安全問題的根本原因是多執行緒並行訪問共享資源,對共享資源加鎖以後,多個執行緒在訪問這個資源的時候必須要先獲得鎖
也就是先獲得訪問資格,而同步鎖的特徵是在同乙個時刻只允許乙個執行緒訪問該資源,直到鎖被釋放。這個方式可以有效的解決執行緒安全問題,但是同時帶來的是加鎖和釋放鎖所產生的效能開銷,因為加鎖
會涉及到使用者空間到核心空間的乙個轉換以及上下文切換,盡量去減少共享物件的使用從業務上實現隔離避免併發。另外在使用lock鎖的時候也需要注意
lock鎖概念
解決多執行緒衝突問題,
lock
是語法糖,
monitor.enter,
佔據乙個引用,別的執行緒就只能等著。鎖的本質就是把多執行緒在某些特定場合下變成單執行緒,來完成某些特定操作。
在日常工作中,有些是特定需要鎖的,更多的時候我們可以把資料拆分,避免多執行緒操作同乙個資料,這樣既安全又高效。例如有
10000
個任務,那可以進行拆分,某個執行緒執行
1-100
給任務。
lock
鎖不允許的型別
string
:string
在記憶體分配上是重用的,會衝突。這麼話應該這麼理解,比如你定義乙個變數
name=」張三」,
再定義乙個變數
temename=」張三」,那麼在
c#記憶體分配時會指向同乙個引用。
null
:可以執行,不能編譯通過。
詳解lock
lock
鎖的兩鐘方式:
lock(this)
不推薦的鎖
如果只是當前內部例項使用,則不會衝突,
外面如果也要用例項,就衝突了
標準鎖微軟推薦的標準鎖
死鎖:一組互相競爭資源的執行緒因為互相等待,導致"永久"阻塞的現象
發生死鎖的原因:
1.互斥條件
共享資源x和y只能被乙個執行緒占用
2占有性等待
執行緒t1已經占有了共享資源x,在等待共享資源y的時候不釋放共享資源x
3不可搶占
其他執行緒不能強行占有執行緒t1占有的資源
4迴圈等待
執行緒t1等待執行緒t2占有的資源,執行緒t2等待執行緒t1占有的資源
如何避免死鎖?
既然我們知道了死鎖的原因是需要同時滿足以上4個條件,那我們只要不同時滿足四個條件即可避免死鎖的發生,而在四個條件中,互斥條件是無法避免的,因為鎖的本質就是通過互斥來解決執行緒安全問題。
對於占有性等待,我們可以一次性申請所有資源,這樣就不存在等待了。對於不可搶占用部分資源的執行緒進一步申請其他資源時,如果申請不到,可以主動釋放它占有的資源,這樣不可搶占的條件就被破壞掉了
對於迴圈等待可以按序申請資源來進行預防
讀寫鎖以及執行緒安全的集合
讀寫鎖實現 讀寫鎖實現執行緒安全的list 讀寫鎖實現 class mylist extends arraylist finally override public object get int index finally override public boolean add object e f...
執行緒安全的實現方式以及鎖優化。
執行緒安全的實現方式 1.互斥同步。臨界區 訊號量 互斥量都是互斥同步的手段。2.非阻塞同步。cas結合不斷重試 3.無鎖 沒有共享資料的時候。鎖優化 1.鎖自旋和自適應自旋 在等待鎖的時候不去掛起執行緒,而是執行乙個忙迴圈,缺點是消耗處理器資源。2.鎖消除。3.鎖粗化 自動擴大使用鎖的範圍 4.輕...
執行緒安全與鎖
1 原子操作 操作只有一步,不會被其他的操作打斷 2 系統一般會帶有一些原子操作的函式留給使用者使用,但是數量較少,並且一般只能用於簡單特定的場合 1 鎖就是乙個flag,他的作用是說現在某個資源正在被某個執行緒使用,別的執行緒都別想輕易的拿去使用,巨集觀上表現就好像是給這些資源新增了乙個鎖,被鎖住...