700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C# 乐观锁 悲观锁 共享锁 排它锁 互斥锁

C# 乐观锁 悲观锁 共享锁 排它锁 互斥锁

时间:2020-08-06 08:49:38

相关推荐

C# 乐观锁 悲观锁 共享锁 排它锁 互斥锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。通过jdbc实现时sql语句只要在整个语句之后加for update即可。例如:select …for update

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适

共享锁:(读取)操作创建的锁。其他用户可以并发读取数据,但任何事物都不能获取数据上的排它锁,直到已释放所有共享锁。 共享锁(S锁)又称为读锁,若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

共享锁的使用

在第一个连接中执行以下语句 begin tran select * from table1 holdlock -holdlock人为加锁 where B='b2' waitfor delay '00:00:30' --等待30秒 commit tran 在第二个连接中执行以下语句 begin tran select A,C from table1 where B='b2' update table1 set A='aa' where B='b2' commit tran 若同时执行上述两个语句,则第二个连接中的select查询可以执行 而update必须等待第一个事务释放共享锁转为排它锁后才能执行 即要等待30秒 排它锁:排它锁又称为写锁((eXclusive lock,简记为X锁)),若事物T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。

排它锁的使用

在第一个连接中执行以下语句

begin tran

update table1

set A='aa'

where B='b2'

waitfor delay '00:00:30' --等待30秒

commit tran

在第二个连接中执行以下语句

begin tran

select * from table1

where B='b2'

commit tran

若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待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();}}}

小结:

悲观锁:查询加锁 【select ...... for update】

乐观锁:修改加锁 【版本号控制】

排它锁:事务A可以查询、修改,直到事务A释放为止才可以执行下一个事务

共享锁:事务A可以查询、修改,同时事务B也可以查询但不能修改

互斥锁:同一资源同一时间只能被一个线程访问

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。