俗話說金三銀四,不論是爲了升職加薪仍是打算換個環境,如今正是廣大程序員們的跳槽季,IT行業正暗流涌動腥風血雨,互聯網寒冬彷佛並無過去,不少企業依然在裁人,還有部分企業光明正大的實行着"996",這一行可能正面臨着最大的競爭壓力和生存壓力。咱們沒法改變環境,也沒法左右市場,可是咱們能改變和左右的是本身的知識深度和廣度,只有武裝到牙齒,不斷的充實本身,才能在面試這場江湖紛爭裏遊刃有餘。mysql
你是否是常常被面試官突如其來的問題問的語無倫次或者毫無底氣?進而在一整場面試裏都失去了信心。最近有個羣員就遇到這個問你,面試官讓他自我介紹之後,就忽然問他mysql的悲觀鎖和樂觀鎖區別,而這正好是他的盲區,第一個問題就被堵住了,這場面試的結果也可想而知。下面就從面試角度來淺談一下,該怎樣回答這個問題。程序員
1、概念上區別面試
樂觀鎖(** Optimistic Locking**):顧名思義,對加鎖持有一種樂觀的態度,即先進行業務操做,不到最後一步不進行加鎖,"樂觀"的認爲加鎖必定會成功的,在最後一步更新數據的時候再進行加鎖。sql
悲觀鎖**(Pessimistic Lock)**:正如其名字同樣,悲觀鎖對數據加鎖持有一種悲觀的態度。所以,在整個數據處理過程當中,將數據處於鎖定狀態。悲觀鎖的實現,每每依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,不然,即便在本系統中實現了加鎖機制,也沒法保證外部系統不會修改數據)。數據庫
2、實現方式:線程
樂觀鎖:code
version方式:通常是在數據表中加上一個數據版本號version字段,表示數據被修改的次數,當數據被修改時,version值會加一。當線程A要更新數據值時,在讀取數據的同時也會讀取version值,在提交更新時,若剛纔讀取到的version值爲當前數據庫中的version值相等時才更新,不然重試更新操做,直到更新成功。內存
sql實現代碼:資源
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS(定義見後)操做方式:即compare and swap 或者 compare and set,涉及到三個操做數,數據所在的內存值,預期值,新值。當須要更新時,判斷當前內存值與以前取到的值是否相等,若相等,則用新值更新,若失敗則重試,通常狀況下是一個自旋操做,即不斷的重試。(這種方式做者也是最近剛知道,慚愧慚愧)io
悲觀鎖:是由數據庫本身實現了的,要用的時候,咱們直接調用數據庫的相關語句就能夠了(原理:共享資源每次只給一個線程使用,其它線程阻塞,用完後再把資源轉讓給其它線程),如行鎖、讀鎖和寫鎖等,都是在操做以前加鎖,在Java中,synchronized的思想也是悲觀鎖。
3、使用場景
樂觀鎖:比較適合讀取操做比較頻繁的場景,若是出現大量的寫入操做,數據發生衝突的可能性就會增大,爲了保證數據的一致性,應用層須要不斷的從新獲取數據,這樣會增長大量的查詢操做,下降了系統的吞吐量。
悲觀鎖:比較適合寫入操做比較頻繁的場景,若是出現大量的讀取操做,每次讀取的時候都會進行加鎖,這樣會增長大量的鎖的開銷,下降了系統的吞吐量。
4、特色
樂觀鎖:樂觀鎖的特色先進行業務操做,不到萬不得已不去拿鎖。即「樂觀」的認爲拿鎖多半是會成功的,所以在進行完業務操做須要實際更新數據的最後一步再去拿一下鎖就好。
悲觀鎖:悲觀鎖的特色是先獲取鎖,再進行業務操做,即「悲觀」的認爲獲取鎖是很是有可能失敗的,所以要先確保獲取鎖成功再進行業務操做。一般所說的「一鎖二查三更新」即指的是使用悲觀鎖。
5、sql實現代碼和案例
由於本文主要是講解的是面試的時候怎樣回答,因此就不將具體sql代碼和案例貼出來了,感興趣的同窗能夠自行去看一下,若是之後有時間,我也會單獨寫一篇詳細的實現案例出來。
總結:以上,基本回答完前四點後,這道題已經能在面試官內心達到八九十分了。可是咱們的人生不只僅是爲了面試,但願同窗們必定要弄懂其中的原理和區別,悲觀鎖和樂觀鎖都有本身的優缺點,簡而言之記得一句話:讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。樂觀鎖不能解決髒讀的問題。
若是以爲本文有用,請推薦給更多有須要的人,謝謝!若是發現問題,歡迎留言,請隨時批評改正,謝謝!