博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET:防止并发修改 之 离线悲观锁代码示例(离线悲观锁)
阅读量:5945 次
发布时间:2019-06-19

本文共 5123 字,大约阅读时间需要 17 分钟。

背景

系统会出现并发,我介绍了如何使用“离线乐观锁”保证并发,离线乐观锁适合处理那些重新编辑成本不大的单据,如果某个单据用户花了10分钟进行编辑,提交时你告诉他出现并发了,他心里肯定会骂娘的,今天介绍的“离线悲观锁”就可以避免这种情况。

思路

小明签出了源代码,小强就不能签出了,我们目前的源代码系统就是用的这种悲观策略。

实现

核心代码

离线悲观锁管理器接口

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Application.PessimisticLock 8 { 9     /// 10     /// 离线悲观锁管理器接口。11     /// 12     public interface ILockManager13     {14         /// 15         /// 获取锁。16         /// 17         /// 锁的主体,如:表名或聚合名。18         /// 锁的主体的唯一标识,如:主键或唯一索引。19         /// 锁的拥有者,如:UserId或SessionId。20         /// 
获取锁成功就返回true,否则返回false。
21 bool AcquireLock(string entity, string key, string owner);22 23 /// 24 /// 释放锁。25 /// 26 /// 锁的主体,如:表名或聚合名。27 /// 锁的主体的唯一标识,如:主键或唯一索引。28 /// 锁的拥有者,如:UserId或SessionId。29 void ReleaseLock(string entity, string key, string owner);30 31 32 /// 33 /// 释拥有者的所有锁。34 /// 35 /// 锁的拥有者,如:UserId或SessionId。36 void ReleaseLocks(string owner);37 }38 }

基于内存的离线悲观锁管理器

1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6   7 using Happy.DesignByContract;  8 using Happy.Application.PessimisticLock.Internal;  9  10 namespace Happy.Application.PessimisticLock 11 { 12     ///  13     /// 基于内存的离线悲观锁管理器。 14     ///  15     public sealed class MemoryLockManager : ILockManager 16     { 17         private static readonly Dictionary
_items = new Dictionary
(); 18 19 ///
20 public bool AcquireLock(string entity, string key, string owner) 21 { 22 entity.MustNotNullAndNotWhiteSpace("entity"); 23 key.MustNotNullAndNotWhiteSpace("key"); 24 owner.MustNotNullAndNotWhiteSpace("owner"); 25 26 var item = MemoryLockItem.Crete(entity, key, owner); 27 28 lock (_items) 29 { 30 if (!IsLocked(item.Identifier)) 31 { 32 SetLockItem(item); 33 34 return true; 35 } 36 37 return IsLockedBy(item); 38 } 39 } 40 41 ///
42 public void ReleaseLock(string entity, string key, string owner) 43 { 44 entity.MustNotNullAndNotWhiteSpace("entity"); 45 key.MustNotNullAndNotWhiteSpace("key"); 46 owner.MustNotNullAndNotWhiteSpace("owner"); 47 48 var item = MemoryLockItem.Crete(entity, key, owner); 49 50 lock (_items) 51 { 52 if (!IsLockedBy(item)) 53 { 54 throw new InvalidOperationException(string.Format(Messages.Error_CanNotReleaseLock, owner)); 55 } 56 57 RemoveLockItem(item); 58 } 59 } 60 61 ///
62 public void ReleaseLocks(string owner) 63 { 64 lock (_items) 65 { 66 foreach (var keypair in _items) 67 { 68 if (keypair.Value.Owner == owner) 69 { 70 RemoveLockItem(keypair.Value); 71 } 72 } 73 } 74 } 75 76 private static bool IsLocked(string identifier) 77 { 78 return _items.ContainsKey(identifier); 79 } 80 81 private static void SetLockItem(MemoryLockItem item) 82 { 83 _items[item.Identifier] = item; 84 } 85 86 private static bool IsLockedBy(MemoryLockItem item) 87 { 88 if (!IsLocked(item.Identifier)) 89 { 90 return false; 91 } 92 93 return _items[item.Identifier].Owner == item.Owner; 94 } 95 96 private static void RemoveLockItem(MemoryLockItem item) 97 { 98 _items.Remove(item.Identifier); 99 }100 }101 }

离线悲观锁代理

1 /** 2  * 离线悲观锁代理。 3  *  4  * @static 5  * @class PessimisticLockProxy 6  * @namespace Happy.server 7  */ 8 Ext.define('Happy.server.PessimisticLockProxy', { 9     alternateClassName: ['PessimisticLockProxy'],10     singleton: true,11     requires: ['Happy.Ajax'],12 13     acquireLock: function (entity, key, success, failure) {14         var me = this;15 16         Happy.Ajax.callAction({17             url: '/LockManager/AcquireLock',18             params: { entity: entity, key: key },19             success: success,20             failure: failure21         });22     },23 24     releaseLock: function (entity, key, success, failure) {25         var me = this;26 27         Happy.Ajax.callAction({28             url: '/LockManager/ReleaseLock',29             params: { entity: entity, key: key },30             success: success,31             failure: failure32         });33     }34 });

运行效果

 

代码下载

地址:。因为项目正在重构中,请下载最新源代码,不要下载。

如何使用代码

备注

尽量通过合理的设计规避离线悲观锁,应用场景不会有很多,有使用过的朋友,请留下您宝贵的意见。

转载自

你可能感兴趣的文章
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
oracle中create table with as和insert into with as语句
查看>>
kafka连接异常
查看>>
11g废弃的Hint - BYPASS_UJVC
查看>>
为什么工业控制系统需要安全防护?
查看>>
Mongodb部署记录[3]-主从搭建
查看>>
hive sql操作
查看>>
tomcat 深度优化
查看>>
127 - "Accordian" Patience
查看>>
阿里云CentOS7安装Oracle11GR2
查看>>
nginc+memcache
查看>>
php正则匹配utf-8编码的中文汉字
查看>>
MemCache在Windows环境下的搭建及启动
查看>>
linux下crontab实现定时服务详解
查看>>
Numpy中的random模块中的seed方法的作用
查看>>
用java数组模拟登录和注册功能
查看>>
javaScript实现归并排序
查看>>
关于jsb中js与c++的相互调用
查看>>
UVA 122 Trees on the level 二叉树 广搜
查看>>
POJ-2251 Dungeon Master
查看>>