作開發,這幾種鎖機制你不得不瞭解一下

摘要:併發訪問共享資源,若是不加鎖,可能會致使數據不一致問題,一般爲了解決併發訪問問題,咱們都會在訪問共享資源以前加鎖,保證同一時刻只有一個線程訪問。下面咱們用問答的方式說明下各類併發鎖的概念、優缺點及其應用場景。

本文分享自華爲雲社區《一文帶你全面理解各類鎖機制》,原文做者:dayu_dls。mysql

併發訪問共享資源,若是不加鎖,可能會致使數據不一致問題,一般爲了解決併發訪問問題,咱們都會在訪問共享資源以前加鎖,保證同一時刻只有一個線程訪問。下面咱們用問答的方式說明下各類併發鎖的概念、優缺點及其應用場景。sql

一、什麼是互斥鎖和自旋鎖,各有什麼優缺點?

互斥鎖和自旋鎖是最底層的兩種鎖,其餘的不少鎖都是基於他們的實現。當線程A獲取到鎖後,線程B再去獲取鎖,有兩種處理方式,第一種是線程B循環的去嘗試獲取鎖,直到獲取成功爲止即自旋鎖,另外一種是線程B放棄獲取鎖,在鎖空閒時,等待被喚醒,即互斥鎖。編程

互斥鎖會釋放當前線程的cpu,致使加鎖的代碼阻塞,直到線程再次被喚醒。互斥鎖加鎖失敗時,會從用戶態陷入到內核態,讓內核幫咱們切換線程,存在必定的性能開銷。segmentfault

  • (1)當線程加鎖失敗,內核會把線程的狀態由「運行」設置爲「睡眠」,讓出cpu;
  • (2)當鎖空閒時,內核喚醒線程,狀態設置爲「就緒」,獲取cpu執行;

而自旋鎖會自用戶態由應用程序完成,不涉及用戶態到內核態的轉化,沒有線程上下文切換,性能相對較好。自旋鎖加鎖過程:多線程

  • (1)查看鎖的狀態;
  • (2)鎖空閒,獲取鎖,不然執行(1);

自旋鎖會利用cpu一直工做直到獲取到鎖,中間不會釋放cpu,但若是被鎖住的代碼執行時間較長,致使cpu空轉,浪費資源。併發

二、什麼是讀寫鎖?

讀寫鎖由讀鎖和寫鎖組成。讀鎖又稱爲共享鎖,S鎖,寫鎖又稱爲排它鎖、X鎖,在mysql的事務中大量使用。寫鎖是獨佔鎖,一旦線程獲取寫鎖,其餘線程不能獲取寫鎖和讀鎖。性能

讀鎖是共享鎖,當線程獲取讀鎖,其餘線程能夠獲取讀鎖不能獲取寫鎖。由於併發數據讀取並不會改變共享數據致使數據不一致。讀寫鎖把對共享資源的讀操做和寫操做分別加鎖控制,可以提升讀線程的併發性,適用於讀多寫少的場景。線程

三、什麼是讀優先鎖、寫優先鎖、公平讀寫鎖?

讀優先鎖但願的是讀鎖可以被更多的線程獲取,能夠提升讀線程的併發性。線程A獲取了讀鎖,線程B想獲取寫鎖,此時會被阻塞,線程c能夠繼續獲取讀鎖,直到A和c釋放鎖,線程B才能夠獲取寫鎖。若是有不少線程獲取讀鎖,且加鎖的代碼執行時間很長,就到致使線程B永遠獲取不到寫鎖。blog

寫優先鎖但願的是寫鎖可以被優先獲取。線程A獲取了讀鎖,線程B想獲取寫鎖,此時會被阻塞,後面獲取讀鎖都會失敗,線程A釋放鎖,線程B能夠獲取寫鎖,其餘獲取讀鎖的線程阻塞。若是有不少寫線程獲取寫鎖,且加鎖的代碼執行時間很長,就到致使讀線程永遠獲取不到讀鎖。隊列

上面兩種鎖都會形成【飢餓】現象,爲解決這種問題,能夠增長一個隊列,把獲取鎖的線程(無論是寫線程仍是讀線程)按照先進先出的方式排隊,每次從隊列中取出一個線程獲取鎖,這種獲取鎖的方式是公平的。

四、什麼是樂觀鎖和悲觀鎖?

樂觀鎖是先修改共享資源,再用歷史數據和當前數據比對驗證這段時間共享數據有沒有被修改,若是沒有被修改,那麼更新數據,若是有其餘線程更新了共享資源,須要從新獲取數據,再更新,驗證,循環往復的重試,直到更新成功。因此當數據更新操做比較頻繁,數據衝突的機率就會比較大,重試的次數就會多,浪費CPU資源。

樂觀鎖其實全程沒有加鎖,也叫無鎖編程,因此針對讀多寫少的場景,併發性能較高,典型的實現MVCC,mysql中會使用MVCC構建一致性讀來保證可重複讀。悲觀鎖是在訪問共享資源以前通通加鎖。當併發衝突機率較高時,樂觀鎖不在適用,悲觀鎖就排上用場。互斥鎖、自旋鎖都是悲觀鎖的實現。

點擊關注,第一時間瞭解華爲雲新鮮技術~

相關文章
相關標籤/搜索