“鎖”,程式設計師不可逾越的鴻溝

treenpool的哎呀發表於2018-03-22

兩個男人相對而坐,離的很近,近到可以聽到彼此的呼吸生 酷酷男率先發問:瞭解鎖多麼 知道點, 酷酷男:解釋下什麼是鎖?

“鎖”,程式設計師不可逾越的鴻溝

一種保護執行緒安全的機制,保證多執行緒運算元據的正確性和一致性,

酷酷男:知道鎖的分類麼?

悲觀鎖,樂觀鎖,獨佔鎖,共享鎖,公平鎖,非公平鎖,分散式鎖,自旋鎖

酷酷男:你怎麼理解樂觀鎖悲觀鎖的

“鎖”,程式設計師不可逾越的鴻溝

大家都放在資料庫來講(其實這兩個概念是屬於計算機的,不要被誤導),以mysql為例,悲觀鎖,主要是表鎖,行鎖還有,間隙鎖,葉鎖,讀鎖,因為這些鎖在使用時勢必引起執行緒阻塞,我們稱之為悲觀 另外樂觀鎖在mysql中其實不存在,只是mvcc的機制,類似樂觀鎖, 你說的mvcc,可以解釋下麼

“鎖”,程式設計師不可逾越的鴻溝

在mysqll的 innodb引擎下,mvcc是實現事務隔離主要方式,通過版本號的方式, 避免資料在不同事務出現錯亂,mvcc只在RR和RC事務級別為,才會生效,其次可以通過mvcc避免寫資料時對於讀的阻塞 眼睛男:具體mvcc機制有什麼? 在每開啟一個事務時,會生成一個事務的版本號,被操作的資料會生成一條新的資料行(臨時),但是在提交前對其他事務是不可見的,對於資料的更新操作成功,會將這個版本號更新到資料的行中,事務提交成功,將新的版本號,更新到此資料行(永久)中,這樣保證了每個事務操作的資料,都是相互不影響的,也不存在鎖的問題; 眼睛男:如果多個事務同時提交,怎麼判斷誰成功 mysql判斷,其實就是誰先提交成功算誰的 酷酷男:那再說下事務吧,

“鎖”,程式設計師不可逾越的鴻溝

事務常說一系列操作要麼都成功要麼都失敗,主要特性acid,事務的的實現主要依賴兩個log:redo-log,undo-log,事務會記錄資料修改前的資料undo-log,修改後的資料放入redo-log,提交成功則用redo-log 更新到磁碟,失敗則使用undo-log將資料恢復到修改前的資料

酷酷男:你認為獨佔鎖,共享鎖怎麼回事 (嗯,獨佔,共享,公平,非公平,自旋鎖這些都是廣泛的概念,很多語言都有,包括作業系統,js的同學請回避) 獨佔鎖持鎖的執行緒只能有一個,共享鎖可以被多個執行緒同時持有

酷酷男:獨佔可以理解,你認為共享的意義是什麼

共享鎖是為了提高程式的併發讀,比如資料的操作有讀有寫,通常寫的操作加鎖,保證資料正確性,而對於讀操作如果無鎖,恰好此時寫讀操作也在進行,讀的資料有可能不是最新資料,如果對讀操作加獨佔鎖,那麼讀讀之間也發生互斥這是不合理,就衍生共享鎖,讀的的操作就用共享的鎖,只對寫互斥,即保證了併發度有保證了正確性,在java中的讀寫鎖就是提供這種機制的

酷酷男:讀寫鎖怎麼工作的?

“鎖”,程式設計師不可逾越的鴻溝

在java中讀寫鎖(ReadWritelock),離不開AbstractQueuedSynchronizer,簡稱AQS這是java實現的一種鎖機制,互斥鎖,讀者寫鎖,條件產量,訊號量,柵欄的都是j基於AQS實現的,工作機制依賴CHL佇列,volatile 關鍵字修飾的狀態符stat,執行緒修改stat成功表示執行緒持鎖成功,失敗了就進CHL佇列等待喚醒,等待喚醒,AQS中還有一個重要的機制自旋,線上程等待喚醒過程中,一旦鎖被釋放會使用自旋(while(!cas()))的方式,不停的嘗試獲取鎖,直到其他執行緒獲取成功或者自己獲取成功 在ASQ中共享與獨佔不同的是,CHL佇列中的節點的模式是EXCLUSIVE還是SHARED,當一個執行緒成功修改了stat狀態,表示獲取了鎖,如果執行緒所在的節點為SHARED,將開始一個讀鎖傳遞的過程,從頭結點,向佇列後續節點傳遞喚醒,直到佇列結束或者遇到了EXCLUSIVE的節點,等待所有啟用的讀操作完成,然後進入到獨享模式 公平與非公平的區別就是一行程式碼,線上程獲取鎖是,,是直接進佇列還是直接修改stat,這是基本的工作機制,詳細的估計可以再聊好久

酷酷男:java 還有那些鎖的實現方式

“鎖”,程式設計師不可逾越的鴻溝

在java中,synchronized關鍵字,稱為內建鎖,被synchronized修飾的方法或者程式碼塊,只允許一個執行緒執行,是典型的獨享鎖,synchronized的機制,可以參考AQS的實現方式,只是AQS使用顯示的用lock.lock()呼叫,對於synchronized,可以認為在修飾的地方,新增了lock方法,結束的地方進行了unlock釋放鎖的方法,只是我們看不到。 它本身實現有兩部分:monitor物件,執行緒,工作機制還是執行緒搶佔物件使用權,物件都有自己的物件頭,儲存了物件的很多資訊,其中有一個是標識被哪個執行緒持有,對比AQS,執行緒從修改stat,變為修改monitor的物件頭,執行緒的等待區域動 AQS中的佇列,變為monitor物件中的某個區域,

“鎖”,程式設計師不可逾越的鴻溝

酷酷男:剛才我們一直圍繞執行緒在聊,那麼鎖在記憶體中的操作過程是什麼

這裡必須要說記憶體模型(這個和jvm不要混淆,The Java memory model used internally in the JVM divides memory between thread stacks and the heap. This diagram illustrates the Java memory model from a logic perspective),是JVM用來區別執行緒棧和堆的記憶體方式,每個執行緒在執行的時候,所操作的資料儲存空間有兩個,主記憶體 工作記憶體,主記憶體其實就是jvm中堆,工作記憶體就是執行緒棧鎖操作的CPU快取區(被所有執行緒共享),每次操作,從主記憶體中把資料讀到工作記憶體中,然後在工作記憶體中進行各種處理,如果資料被修改,會把資料回寫到主記憶體,然後其他執行緒又進行同樣的操作,就這樣資料在工作記憶體和主記憶體,進進出出,不亦樂乎,在多執行緒的情況,就是因為進進出出的順序亂了,不是按照執行緒預期的訪問順序,就出現了資料不一致的問題,導致了多執行緒的不安全性;

酷酷男:記憶體模型還要那些可以聊的?

happen-befor 原則,Volatile 關鍵字(,記憶體屏障

酷酷男:哦(慫了慫了)

“鎖”,程式設計師不可逾越的鴻溝

happen-befor原則定義了記憶體模型執行過程中的定律,就像1+1 = 2,不可能被打破的jvm的執行機制都依賴於這個原則,是jvm的法律!!! Volatile關鍵字就有點厲害了,Volatile修飾的資料,在被某個執行緒修改後,會被的回寫到主記憶體(寫的事時間不一定),然後其他執行緒再獲取時,就是新的資料,聽起來很美好,但是Volatile沒有辦法控制執行緒的順序,當一個資料(新資料)即將被修改到主記憶體時,剛好,另外一個執行緒從主記憶體讀了資料(老資料),並又進行了一波操作,又將資料(更新的資料)回寫到了主記憶體,整個過程(新資料)完全沒有起到一毛錢作用,最終導致了資料的錯誤,呼呼打完收工!!!!

你懂的很多麼 那是因為我帥, 有多帥? 可以用微笑殺死你 來啊!

“鎖”,程式設計師不可逾越的鴻溝

猝 享年28歲!!!

。。。。。end。。。。。。

下面我們看下“鎖”範圍內的知識覆蓋體系有那些

“鎖”,程式設計師不可逾越的鴻溝

更詳細的請開啟http://treenpool.com/html/index.html?branchId=488

歡迎大家加微信騷擾:treenpool 關注微信公眾號:treenpool,更多好文在裡面 請持續關注,treenpool.com

相關文章