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