C# 乐观锁、悲观锁、共享锁、排它锁、互斥锁
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。?通過?jdbc?實(shí)現(xiàn)時?sql?語句只要在整個語句之后加?for update?即可。例如:?select …for update
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號等機(jī)制。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫如果提供類似于write_condition機(jī)制的其實(shí)都是提供的樂觀鎖。
兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下,即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。但如果經(jīng)常產(chǎn)生沖突,上層應(yīng)用會不斷的進(jìn)行retry,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適
?
共享鎖:(讀取)操作創(chuàng)建的鎖。其他用戶可以并發(fā)讀取數(shù)據(jù),但任何事物都不能獲取數(shù)據(jù)上的排它鎖,直到已釋放所有共享鎖。 共享鎖(S鎖)又稱為讀鎖,若事務(wù)T對數(shù)據(jù)對象A加上S鎖,則事務(wù)T只能讀A;其他事務(wù)只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這就保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。共享鎖的使用
在第一個連接中執(zhí)行以下語句 begin tran select * from table1 holdlock -holdlock人為加鎖 where B='b2' waitfor delay '00:00:30' --等待30秒 commit tran 在第二個連接中執(zhí)行以下語句 begin tran select A,C from table1 where B='b2' update table1 set A='aa' where B='b2' commit tran 若同時執(zhí)行上述兩個語句,則第二個連接中的select查詢可以執(zhí)行 而update必須等待第一個事務(wù)釋放共享鎖轉(zhuǎn)為排它鎖后才能執(zhí)行 即要等待30秒 排它鎖:排它鎖又稱為寫鎖((eXclusive lock,簡記為X鎖)),若事物T對數(shù)據(jù)對象A加上X鎖,則只允許T讀取和修改A,其它任何事務(wù)都不能再對A加任何類型的鎖,直到T釋放A上的鎖。它防止任何其它事務(wù)獲取資源上的鎖,直到在事務(wù)的末尾將資源上的原始鎖釋放為止。排它鎖的使用
在第一個連接中執(zhí)行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
select * from table1
where B='b2'
commit tran
若同時執(zhí)行上述兩個語句,則select查詢必須等待update執(zhí)行完畢才能執(zhí)行即要等待30秒
?
互斥鎖(Mutex)
互斥鎖是一個互斥的同步對象,意味著同一時間有且僅有一個線程可以獲取它。
互斥鎖可適用于一個共享資源每次只能被一個線程訪問的情況
using System; using System.Collections.Generic; using System.Linq; using System.Text;using System.Threading;namespace MyTTCon {class shareRes{public static int count = 0;public static Mutex mutex = new Mutex();}class IncThread{int number;public Thread thrd;public IncThread(string name, int n){thrd = new Thread(this.run);number = n;thrd.Name = name;thrd.Start();}void run(){Console.WriteLine(thrd.Name + "正在等待 the mutex");//申請 shareRes.mutex.WaitOne();Console.WriteLine(thrd.Name + "申請到 the mutex");do{Thread.Sleep(1000);shareRes.count++;Console.WriteLine("In " + thrd.Name + "ShareRes.count is " + shareRes.count);number--;} while (number > 0);Console.WriteLine(thrd.Name + "釋放 the nmutex");// 釋放 shareRes.mutex.ReleaseMutex();}}class DecThread{int number;public Thread thrd;public DecThread(string name, int n){thrd = new Thread(this.run);number = n;thrd.Name = name;thrd.Start();}void run(){Console.WriteLine(thrd.Name + "正在等待 the mutex");//申請 shareRes.mutex.WaitOne();Console.WriteLine(thrd.Name + "申請到 the mutex");do{Thread.Sleep(1000);shareRes.count--;Console.WriteLine("In " + thrd.Name + "ShareRes.count is " + shareRes.count);number--;} while (number > 0);Console.WriteLine(thrd.Name + "釋放 the nmutex");// 釋放 shareRes.mutex.ReleaseMutex();}}class Program{static void Main(string[] args){IncThread mthrd1 = new IncThread("IncThread thread ", 5);DecThread mthrd2 = new DecThread("DecThread thread ", 5);mthrd1.thrd.Join();mthrd2.thrd.Join();}} }?小結(jié):
悲觀鎖:查詢加鎖 【select ...... for update】
樂觀鎖:修改加鎖 【版本號控制】
排它鎖:事務(wù)A可以查詢、修改,直到事務(wù)A釋放為止才可以執(zhí)行下一個事務(wù)
共享鎖:事務(wù)A可以查詢、修改,同時事務(wù)B也可以查詢但不能修改
互斥鎖:同一資源同一時間只能被一個線程訪問
轉(zhuǎn)載于:https://www.cnblogs.com/smile-live/p/7644583.html
總結(jié)
以上是生活随笔為你收集整理的C# 乐观锁、悲观锁、共享锁、排它锁、互斥锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分页的代码
- 下一篇: iKcamp出品|全网最新|微信小程序|