簡(jiǎn)介:編程中的鎖是一種同步機(jī)制,用于控制對(duì)共享資源的訪問(wèn),確保同一時(shí)間只有一個(gè)線程可以訪問(wèn)共享資源,從而避免競(jìng)態(tài)條件和其他并發(fā)問(wèn)題,保證線程安全和正確的數(shù)據(jù)訪問(wèn)。鎖的概念來(lái)源于日常生活,其中鎖和鑰匙用于控制對(duì)某個(gè)空間的訪問(wèn),確保安全隱私。在編程中,鎖用于控制對(duì)共享資源訪問(wèn),防止多個(gè)線程同一時(shí)間修改同一數(shù)據(jù),從而引發(fā)數(shù)據(jù)不一致的問(wèn)題。鎖的實(shí)現(xiàn)方式多種多樣,包括悲觀鎖和樂(lè)觀鎖等,具體選用哪種取決于應(yīng)用程序的特定需求和并發(fā)控制的復(fù)雜性。
一丶Mysql的鎖分類
在Mysql中鎖也分為很多種,按照不同維度有不同分法:
從業(yè)務(wù)上分為樂(lè)觀鎖(用版本對(duì)比來(lái)實(shí)現(xiàn))和悲觀鎖
從數(shù)據(jù)庫(kù)操作類型來(lái)分,分為讀鎖和寫鎖(都是數(shù)據(jù)悲觀鎖的范疇)
讀鎖(共享鎖、S鎖Shard)):針對(duì)同一份數(shù)據(jù),多個(gè)讀操作可以同時(shí)進(jìn)行而不會(huì)互相影響
寫鎖(排它鎖、X鎖Exclusive):當(dāng)前寫操作沒(méi)有完成前、它會(huì)阻斷其它寫鎖和讀鎖
從對(duì)數(shù)據(jù)操作顆粒來(lái)分:分為表鎖和行鎖
二丶樂(lè)觀鎖和悲觀鎖
樂(lè)觀鎖和悲觀鎖是按照加鎖機(jī)制進(jìn)行分類的,是一種設(shè)計(jì)理念,并不是具體的某把鎖,樂(lè)觀鎖和悲觀鎖不僅適用于數(shù)據(jù)庫(kù)也適用于Java應(yīng)用中或其他中間件:Redis、ElasticSearch
悲觀鎖:悲觀鎖的設(shè)計(jì)理念是悲觀的,認(rèn)為總有線程并發(fā)問(wèn)題導(dǎo)致數(shù)據(jù)不安全,所以在整個(gè)數(shù)據(jù)處理的過(guò)程中,將數(shù)據(jù)處于鎖定狀態(tài),數(shù)據(jù)處理完成后釋放鎖(一般是事務(wù)提交之后)。悲觀鎖的實(shí)現(xiàn)往往依靠數(shù)據(jù)庫(kù)提供鎖機(jī)制。通常是在select語(yǔ)句后面增加for update來(lái)鎖定數(shù)據(jù)。其實(shí)對(duì)于Synchronized、Lock等鎖也是一種悲觀鎖:舉例在Java中的用法。
1. 查詢User,通過(guò) select id,amount from Account where id = 1 for update 加鎖
2. 在業(yè)務(wù)代碼中修改amount的值
3. 執(zhí)行update,完成事務(wù)提交了
樂(lè)觀鎖:樂(lè)觀鎖是相對(duì)悲觀鎖而言,樂(lè)觀鎖假設(shè)數(shù)據(jù)一般情況下不會(huì)造成沖突,在數(shù)據(jù)處理的過(guò)程中不會(huì)加鎖,在數(shù)據(jù)進(jìn)行提交更新的時(shí)候(update更新到數(shù)據(jù)庫(kù)時(shí)),才會(huì)對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè),如果發(fā)現(xiàn)沖突則拋出異常。在數(shù)據(jù)庫(kù)中通常使用Version版本號(hào)、或者時(shí)間戳、或者UUID來(lái)實(shí)現(xiàn)樂(lè)觀鎖,Atomicinterger等原子類、ElasticSearch也是通過(guò)樂(lè)觀鎖來(lái)控制并發(fā)修改。
三丶共享鎖和排它鎖
在Mysql中按數(shù)據(jù)的讀寫操作分為:共享鎖(讀鎖)和排它鎖(寫鎖),共享鎖意味著多個(gè)事務(wù)可以獲取到同一把鎖,通常是用于讀操作;而排它鎖是相互排斥的,只可能有一個(gè)事務(wù)獲取排他鎖,通常發(fā)生在寫操作上。
讀鎖(Shard Lock)共享鎖:又稱為S鎖,允許多個(gè)事務(wù)同事獲取該鎖,也就是允許事務(wù)同時(shí)讀取一條數(shù)據(jù)。當(dāng)一個(gè)事務(wù)為數(shù)據(jù)加上讀鎖之后,其他事務(wù)只能對(duì)該數(shù)據(jù)加上讀鎖,而不能對(duì)數(shù)據(jù)加寫鎖,直到所有的讀鎖釋放之后其他事物才能對(duì)其進(jìn)行加持寫鎖。共享鎖的特性主要是為了支持并發(fā)的讀取數(shù)據(jù),讀取數(shù)據(jù)的時(shí)候不支持修改,避免出現(xiàn)重復(fù)讀的問(wèn)題。
在select語(yǔ)句末尾加上lock in share mode關(guān)鍵字即可加共享鎖。
寫鎖(Exclusive Lock)排它鎖:又稱X鎖,當(dāng)一個(gè)事物為數(shù)據(jù)加上寫鎖時(shí),其他請(qǐng)求將不能再為數(shù)據(jù)加上任何鎖,知道該鎖釋放之后,其他事務(wù)才能對(duì)數(shù)據(jù)進(jìn)行加鎖。排它鎖的目的是在數(shù)據(jù)修改的時(shí)候,不允許其它同時(shí)修改,也不允許其他人讀取,避免出現(xiàn)臟數(shù)據(jù)(臟讀)的問(wèn)題,Mysql在執(zhí)行寫操作時(shí)默認(rèn)會(huì)加上排他鎖,或者我們也可以在語(yǔ)句末尾加上for update關(guān)鍵字來(lái)實(shí)現(xiàn)排他鎖。
意向鎖(Intention Lock):又稱I鎖,針對(duì)表鎖主要為了提高加表鎖的效率,是Mysql自己加的。當(dāng)有事務(wù)給表的數(shù)據(jù)行加了共享鎖或排它鎖,同時(shí)會(huì)給自己設(shè)定一個(gè)表示,代表已經(jīng)有行鎖了,其他事務(wù)要想對(duì)表加表鎖時(shí),就不必逐行判斷有沒(méi)有行鎖可能跟表鎖沖突了,直接讀這個(gè)標(biāo)識(shí)就可以確定自己該不該加表鎖。特別是表中記錄很多的時(shí)候,逐行判斷加表鎖的方式效率就會(huì)很低,這個(gè)標(biāo)識(shí)就是意向鎖。 意向鎖主要分為:
意向共享鎖:IS鎖,對(duì)整個(gè)表加共享鎖(讀鎖)之前,需要先獲取意識(shí)共享鎖;
意識(shí)排它鎖:IX鎖,對(duì)整個(gè)表加怕他鎖(寫鎖)之前,需要先獲取意識(shí)排它鎖;
付費(fèi)1元即可閱讀全文