房間里燈光昏暗,兩個男人相對而坐,
良久髓梅,眼睛男率先打破僵局拟蜻,
眼睛男,知道鎖么
帥氣男枯饿,知道些酝锅,
眼睛男:什么是鎖?
一種保護機制,在多線程的情況下奢方,保證操作數(shù)據(jù)的正確性/一致性搔扁,
眼鏡男:有哪幾種分類?
悲觀鎖蟋字,樂觀鎖稿蹲,獨占鎖,共享鎖鹊奖,公平鎖苛聘,非公平鎖,分布式鎖忠聚,自旋鎖
眼睛男:講講樂觀鎖悲觀鎖吧
一般喜歡放在數(shù)據(jù)庫來講(其實這兩個概念是屬于計算機的设哗,不要被誤導(dǎo)),就說mysql吧两蟀,悲觀鎖网梢,主要是表鎖,行鎖還有間隙鎖赂毯,葉鎖战虏,讀鎖,因為這些鎖在被觸發(fā)的時候勢必引起線程阻塞党涕,所以叫悲觀烦感,另外樂觀鎖其實在mysql本身中不存在的,但是mysql提供了種mvcc的機制膛堤,支持樂觀鎖機制啸盏,
眼睛男:mvcc是咋回事?
只是在innodb引擎下存在骑祟,mvcc是為了滿足事務(wù)的隔離,通過版本號的方式气笙,避免同一數(shù)據(jù)不同事務(wù)間的競爭次企,所說的樂觀鎖只在事務(wù)級別為讀未提交讀提交,才會生效潜圃,
眼睛男:具體mvcc機制有什么缸棵?
多版本并發(fā)控制,保證數(shù)據(jù)操作在多線程過程中谭期,保證事務(wù)隔離的機制堵第,可以降低鎖競爭的壓力吧凉,保證比較高并發(fā)量,這個過程踏志。在每開啟一個事務(wù)時阀捅,會生成一個事務(wù)的版本號,被操作的數(shù)據(jù)會生成一條新的數(shù)據(jù)行(臨時)针余,但是在提交前對其他事務(wù)是不可見的饲鄙,對于數(shù)據(jù)的更新操作成功,會將這個版本號更新到數(shù)據(jù)的行中,事務(wù)提交成功圆雁,將新的版本號忍级,更新到此數(shù)據(jù)行(永久)中,這樣保證了每個事務(wù)操作的數(shù)據(jù)伪朽,都是相互不影響的轴咱,也不存在鎖的問題;
眼睛男:那么在多個事務(wù)(操作同一條數(shù)據(jù))并發(fā)過程中烈涮,誰先成功?
mysql判斷朴肺,其實就是誰先提交成功算誰的
眼睛男:說到事務(wù)了,聊聊事務(wù)跃脊,
事務(wù)常說一系列操作作為一個整體要么都成功要么都失敗宇挫,主要特性acid,事務(wù)的的實現(xiàn)主要依賴兩個log redo-log,undo-log,每次事務(wù)都會記錄數(shù)據(jù)修改前的數(shù)據(jù)undo-log酪术,修改后的數(shù)據(jù)放入redo-log,提出成功則使用redo-log 更新到磁盤器瘪,失敗則使用undo-log將數(shù)據(jù)恢復(fù)到事務(wù)之前的數(shù)據(jù)
眼鏡男,嗯绘雁,再說說獨占鎖橡疼,共享鎖吧
(嗯,獨占庐舟,共享欣除,公平,非公平挪略,自旋鎖這些都是廣泛的概念历帚,很多語言都有,包括操作系統(tǒng)杠娱,js的同學(xué)請回避)
獨占鎖很明顯就是持鎖的線程只能有一個挽牢,共享鎖則可以有多個
眼睛男:獨占可以理解,共享的意義在哪里摊求?
共享鎖是為了提高程序的效率禽拔,舉個例子數(shù)據(jù)的操作有讀寫之分,對于寫的操作加鎖,保證數(shù)據(jù)正確性睹栖,而對于讀的操作如果不加鎖硫惕,在寫讀操作同時進行時,讀的數(shù)據(jù)有可能不是最新數(shù)據(jù)野来,如果對讀操作加獨占鎖恼除,面對讀多寫少的程序肯定效率很低,所有就出現(xiàn)了共享鎖梁只,對于讀的的操作就使用共享的概念缚柳,但是對于寫的操作則是互斥的,保證了讀寫的數(shù)據(jù)操作都一致搪锣,在java中上述的鎖叫讀寫鎖
眼睛男:讀寫鎖的機制是什么呢秋忙?
在java中讀寫鎖(ReadWritelock)的機制是基于AQS的一種實現(xiàn),保證讀讀共享构舟,讀寫互斥灰追,寫寫互斥,如果要說機制的話狗超,還要從AQS說起弹澎,這是java實現(xiàn)的一種鎖機制,互斥鎖努咐,讀者寫鎖苦蒿,條件產(chǎn)量,信號量渗稍,柵欄的都是它的衍生物佩迟,主要工作基于CHL隊列,voliate關(guān)鍵字修飾的狀態(tài)符stat竿屹,線程去修改狀態(tài)符成功了就是獲取成功报强,失敗了就進隊列等待,等待喚醒拱燃,AQS中還有很重要的一個概念是自旋秉溉,在等待喚醒的時候,很多時候會使用自旋(while(!cas()))的方式碗誉,不停的嘗試獲取鎖召嘶,直到被其他線程獲取成功
公平與非公平的區(qū)別就在于線程第一次獲取鎖時,也就是執(zhí)行修改stat操作時哮缺,是進隊列還是直接修改狀態(tài)苍蔬,這是基本的工作機制,詳細的估計可以再聊好幾集
眼睛男:java 除了AQS 還有其他的鎖支持么
在java中蝴蜓,synchronized關(guān)鍵字,是語言自帶的,也叫內(nèi)置鎖茎匠,synchronized關(guān)鍵字格仲,我們都知道被synchronized修飾的方法或者代碼塊,在同一時間內(nèi)诵冒,只允許一個線程執(zhí)行凯肋,是明顯的獨享鎖,synchronized的實現(xiàn)機制汽馋?可以參考AQS的實現(xiàn)方式侮东,只是AQS使用顯示的用lock.lock()調(diào)用,而sync作為關(guān)鍵字修飾豹芯,你可以認為在synchronized修飾的地方悄雅,自動添加了lock方法,結(jié)束的地方進行了unlock釋放鎖的方法铁蹈,只是被隱藏了宽闲,我們看不到。它本身實現(xiàn)有兩部分:monitor對象握牧,線程容诬,工作機制還是線程搶占對象使用權(quán),對象都有自己的對象頭沿腰,存儲了對象的很多信息览徒,其中有一個是標(biāo)識被哪個線程持有,對比AQS颂龙,線程從修改stat习蓬,變?yōu)樾薷膍onitor的對象頭,線程的等待區(qū)域動 AQS中的隊列厘托,變?yōu)閙onitor對象中的某個區(qū)域友雳,
眼睛男:能細說么?
鎖一直是圍繞線程安全來實現(xiàn)的铅匹,比如獨占鎖押赊,它在內(nèi)存里面的操作是怎么樣的,這個地方涉及到一個概念包斑,內(nèi)存模型(這個和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用來區(qū)別線程棧和堆的內(nèi)存方式罗丰,每個線程在運行的時候神帅,所操作的數(shù)據(jù)存儲空間有兩個,一個是主內(nèi)存 一個是工作內(nèi)存萌抵,主內(nèi)存其實就是jvm中堆找御,工作內(nèi)存就是線程的棧元镀,每次的數(shù)據(jù)操作,都是從主內(nèi)存中把數(shù)據(jù)讀到工作內(nèi)存中霎桅,然后在工作內(nèi)存中進行各種處理栖疑,如果進行了修改,會把數(shù)據(jù)回寫到主內(nèi)存滔驶,然后其他線程又進行同樣的操作遇革,就這樣數(shù)據(jù)在工作內(nèi)存和主內(nèi)存,進進出出揭糕,不亦樂乎萝快,在多次的情況下,就是因為進進出出的順序亂了著角,不是按照線程預(yù)期的訪問順序揪漩,就出現(xiàn)了數(shù)據(jù)不一致的問題,導(dǎo)致了多線程的不安全性雇寇;整個操作過程還牽涉到CPU氢拥,高速緩存等概念,略過锨侯。嫩海。。囚痴。
眼睛男:內(nèi)存模型 還有哪些可以聊聊的(我們是抱著學(xué)習(xí)的心態(tài))
happen-befor 原則叁怪,Volatile 關(guān)鍵字(線程的可見性),內(nèi)存屏障
眼睛男:哦(慫了慫了)
happen-befor原則定義了內(nèi)存模型執(zhí)行過程中的定律深滚,就像1+1 = 2奕谭,不可能被打破的jvm的運行機制都依賴于這個原則,是jvm的憲法3占觥Q!
Volatile關(guān)鍵字就有點叼了生兆,Volatile修飾的數(shù)據(jù)难捌,在被某個線程修改后,會被及時的回寫到主內(nèi)存鸦难,然后其他線程再獲取時根吁,就是新的數(shù)據(jù),聽起來很美好合蔽,但是Volatile沒有辦法控制線程的順序击敌,當(dāng)一個數(shù)據(jù)(新數(shù)據(jù))即將被修改到主內(nèi)存時,剛好拴事,另外一個線程從主內(nèi)存讀了數(shù)據(jù)(老數(shù)據(jù))沃斤,并又進行了一波操作圣蝎,又將數(shù)據(jù)(更新的數(shù)據(jù))回寫到了主內(nèi)存,整個過程(新數(shù)據(jù))完全沒有起到一毛錢作用轰枝,最終導(dǎo)致了數(shù)據(jù)的錯誤捅彻,呼呼打完收工!0霸伞!从隆!
眼鏡男:你為啥知道這么多
因為我?guī)洶诚撵。?/i>
眼鏡男:有多帥?
可以用微笑殺死你
眼鏡男:來凹搿寿烟!
眼睛男猝 享年28歲!P猎铩筛武!
。挎塌。徘六。。榴都。end待锈。。嘴高。竿音。。拴驮。
整個文章以“鎖”為半徑春瞬,構(gòu)建了一個簡單的知識體系,直觀的感受一下
更詳細的請打開http://treenpool.com/html/index.html?branchId=488
本文旨在為大家擴寬思路套啤,認識一下不太常見的概念宽气,不要太糾結(jié)于細節(jié)!8倭搿Dㄖ瘛(慫了慫了),這是以點及面比較好的例子止潮,從一個點不斷深入窃判,你會發(fā)現(xiàn)很多新的東西,而這些就是需要一點一滴咀嚼的喇闸,看博客或者視頻都是經(jīng)過別人嚼爛消化過的東西袄琳,然后再吐出來展示給大家询件,大家看看他吃的啥就行,千萬不要再吃下去唆樊,因為真正的養(yǎng)分已經(jīng)不多了宛琅,還是需要從書啃起,一口口嚼出來逗旁,經(jīng)過味蕾嘿辟,大腦,胃片效,大腸红伦。。淀衣。昙读。一點點吸收,才是自己的膨桥,這也是我個人平時學(xué)習(xí)的方法蛮浑,也祝愿大家可以用自己的方法,不斷提升自己只嚣,擴展自己的知識體系沮稚;本文很多描述的不是很完全,畢竟每個點隨隨便便就是幾千字的介牙,本人能力有限壮虫,只能把最近吃的吐出來給大家看看,不知道是否符合大家的胃口环础,
最后G羲啤!线得!高能預(yù)警
歡迎大家加微信騷擾:treenpool
請持續(xù)關(guān)注饶唤,http://treenpool.com 致力于搭建個人知識體系的網(wǎng)站