1. 程式人生 > >關於併發效能和併發安全隨想

關於併發效能和併發安全隨想

一直以來,我理解的併發程式設計包括兩個方面,一個是併發效能,另一個則是併發安全。

在併發效能上,通過具體的編碼能做的事情不多,從本質上來說,一些併發程式設計的編碼方式比如鎖機制等必然會降低系統吞吐量即降低效能,當然是無鎖快,我們能做的只是盡力提高併發效能。其實提高併發效能的主要方式還是通過一些中介軟體以及合理的架構方式。比如用Redis實現快取以及分散式甚至微服務等專案架構,這些途徑提高併發效能卓有成效。相比之下,想通過苛求編碼的細節去提高併發效能顯得微不足道,有時候為了考慮程式碼的可讀性以及編碼風格等因素甚至可以放棄。

在併發安全上,我理解的地方也有兩個方面,一個是涉及到多執行緒工作記憶體與主記憶體的讀寫造成的併發安全問題,另一個則是涉及到資料庫,多執行緒同時修改表中一行等這些行為,可能造成錯誤修改等情況。有一個需要注意一下,一個程序是不會造成表死鎖的,因為一個程序下的多個執行緒的事務會有事務等待,但是不同程序中的執行緒同時操作表中一行就可能造成表死鎖,比如程式中操作表的時候觸發表的觸發器就可能造成表死鎖,因為這裡有兩個程序,一個是程式的主程序,而觸發器是資料庫的程序。

前文說到的併發安全兩個方面都可以通過加鎖的方式去解決,同時只允許一個執行緒工作就沒問題了,也都可以通過無鎖的方式解決,前者有CAS機制,後者有樂觀鎖。其實這種說法不準確,因為CAS就是樂觀鎖的一種,而synchronized或者lock等這些鎖機制也可以稱為悲觀鎖,樂觀鎖和悲觀鎖是兩個大概念,只不過在資料庫中稱為樂觀鎖和悲觀鎖稱習慣了。

重點總結一下資料庫的樂觀鎖和悲觀鎖。

悲觀鎖很簡單,有兩大類分別為共享鎖和排他鎖,使用悲觀鎖要寫具體的SQL語句,即悲觀鎖是資料庫自帶的,體現在SQL中,通過SQL語句可以實現增刪改查的時候鎖住一行等操作,具體的語句書寫可以積累。

樂觀鎖一般是針對更新操作而言的。樂觀鎖不是資料庫自帶的,需要自己去設計表結構,通常是這麼實現的:先給表加一個欄位version,每次對該表的操作都會將對應行的version加1。如果有一個更新操作,操作之前先查出該行的version,再update的時候加一個where條件判斷version是否相同。如果version相同就說明在這段時間內沒有其他執行緒修改這行,即可以更新。如果version不同就說明在這段時間內這行被其他執行緒修改了,即不可以更新,where條件判斷不成立也不會去執行這條更新sql了。