惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
Schneier on Security
Schneier on Security
B
Blog RSS Feed
aimingoo的专栏
aimingoo的专栏
P
Proofpoint News Feed
A
About on SuperTechFans
Recorded Future
Recorded Future
Recent Announcements
Recent Announcements
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
The GitHub Blog
The GitHub Blog
Google DeepMind News
Google DeepMind News
T
Tailwind CSS Blog
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
V2EX - 技术
V2EX - 技术
N
Netflix TechBlog - Medium
F
Fortinet All Blogs
V
Visual Studio Blog
Martin Fowler
Martin Fowler
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Exploit Database - CXSecurity.com
F
Full Disclosure
Scott Helme
Scott Helme
H
Heimdal Security Blog
博客园 - 叶小钗
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
Application and Cybersecurity Blog
Application and Cybersecurity Blog
V
Vulnerabilities – Threatpost
Blog — PlanetScale
Blog — PlanetScale
Security Latest
Security Latest
WordPress大学
WordPress大学
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Troy Hunt's Blog
S
SegmentFault 最新的问题
Forbes - Security
Forbes - Security
Jina AI
Jina AI
S
Securelist
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
J
Java Code Geeks
AWS News Blog
AWS News Blog
N
News and Events Feed by Topic
博客园 - 三生石上(FineUI控件)
量子位

博客园 - henry

Smark.Net.Tcp.XmlService性能测试程序 基于Flex的http简易文件管理工具 性能的瓶颈到底在那呢? 运用Smark.SocketAsyncs扩展基于XML的TCP服务 运用Smark.SocketAsyncs方便实现数据交互服务 发布一个C#实现的Asterisk的管理系统 asterisk使用SIP相互对接 开源一个基于Flex4+C#的个人信息管理程序 FlashBuilder4试用 这样的重构是否有必要呢? Asterisk2B用户管理逻辑设计 用JQuery UI dialog实现Alert和Confirm功能 - henry Asterisk发起电话预约回拔 WOW工会DKP管理系统 我的分页控件设计 实现一个JavaScript验证的Asp.net Helper - henry - 博客园 Smark.Data 实体属性值描述 Smark.Data实体成员数据验证 Smark.Data Part1
实现分布式对象锁
henry · 2010-06-08 · via 博客园 - henry

在数据操作中经常需要锁一个对象来达到数据同步的目的;在一个应用程序中锁对象比较方便,因为c#提供了线程锁对象功能,但如果是不同服务器的数据操作需要锁对象就必须做一个对象锁服务了。
制定功能方法:

  1. Enter(string owner,string id, int milliseconds)
    获取对象锁,直到获取拥用权再往下走
    owner:锁的拥有者
    id:锁的标识
    milliseconds:锁对象的时间,超过这个时间即使程序没有释放标识,组件自动释放
    Exit(string owner,string id)
    owner:锁的拥有者
  2. TryEnter(string owner, string id, int milliseconds, int timeout)
    获取对象锁,在指定时间内没有获取相关标识的锁就放弃往下执行
    owner:锁的拥有者
    id:锁的标识
    milliseconds:锁对象的时间,超过这个时间即使程序没有释放标识,组件自动释放
    timeout:超时时间
  3. TryEnter(string id, int milliseconds, int timeout, Smark.Core.AsyncDelegate<string> lockhandler)
    获取对象锁,根据情况调用相关回委托
    owner:锁的拥有者
    id:锁的标识
    milliseconds:锁对象的时间,超过这个时间即使程序没有释放标识,组件自动释放
    timeout:超时时间
    lockhandler:委托

代码

public class ObjectEnter:IDisposable
    {
        
private string mOwnerID;
        
static ObjectEnter()
        {
            Core.Functions.Action(CheckExpires);
        }
        
public ObjectEnter(string id)
        {
            mOwnerID 
= Guid.NewGuid().ToString("N");
            mID 
= id;
            Enter(mOwnerID, id, 
60000);
        }
        
public ObjectEnter(string id, int milliseconds)
        {
            mOwnerID 
= Guid.NewGuid().ToString("N");
            mID 
= id;
            Enter(mOwnerID, id, milliseconds);
        }
        
private string mID = null;
        
private static Dictionary<string, LockItem> mObjectTable = new Dictionary<string, LockItem>(100);
        
public static void TryEnter(string id, Smark.Core.AsyncDelegate<string,bool> lockhandler)
        {
            TryEnter(id, 
6000030000, lockhandler);
        }
        
public static void TryEnter(string id, int milliseconds, int timeout, Smark.Core.AsyncDelegate<string,bool> lockhandler)
        {
            
string owner = Guid.NewGuid().ToString("N");
            
if(lockhandler!=null)
                lockhandler(owner,TryEnter(owner, id, milliseconds, timeout));
            
        }
        
public static bool TryEnter(string owner, string id, int milliseconds, int timeout)
        {
            QueueState state 
= new QueueState();
            state.EntrerMilliseconds 
= milliseconds;
            state.TimeOut 
= timeout;
            
if (!GetLockItem(id).Enter(owner, milliseconds, state))
            {
                state.Handler.Reset();
                state.Handler.WaitOne(state.TimeOut);
                
return GetLockItem(id).Enter(owner, milliseconds, null);  
            }
            
else
            {
                
return true;
            }

        }

public static void Enter(string owner,string id, int milliseconds)
        {
            QueueState state 
= new QueueState();
            state.EntrerMilliseconds 
= milliseconds;
            
if (!GetLockItem(id).Enter(owner, milliseconds, state))
            {
                state.Handler.Reset();
                state.Handler.WaitOne();                
            }
            
        }
        
public static void Exit(string owner,string id)
        {
            
if (mObjectTable.ContainsKey(id))
                 mObjectTable[id].Exit(owner);
        
        }
        
private static LockItem GetLockItem(string id)
        {
            
lock (mObjectTable)
            {
                LockItem item 
= null;
                
if (!mObjectTable.ContainsKey(id))
                {
                    item 
= new LockItem();
                    item.ID 
= id;
                    mObjectTable.Add(id, item);
                }
                
else
                {
                    item 
= mObjectTable[id];
                }
                
return item;
            }

        }

private static void CheckExpires()
        {
            
while (true)
            {
                
lock (mObjectTable)
                {
                    
foreach (System.Collections.Generic.KeyValuePair<string, LockItem> item in mObjectTable)
                    {
                        item.Value.Expires();
                    }
                }
                System.Threading.Thread.Sleep(
5000);
            }
        }
        
class LockItem
        {
            
const string SYSTEM_ID = "SYSTEM_4EB49CA1-7470-44af-94DE-B2128B9B5BA9";
            
public LockItem()
            {
                
            }
            
public bool Enter(string owner, int milliseconds, QueueState handler)
            {
                
lock (this)
                {
                    
if (Count>0 && owner != Owner)
                    {
                      
                        
if (handler != null)
                            EnterWait(handler);
                        
return false;
                    }
                    Count
++;
                    EntrerMilliseconds 
= milliseconds;
                    EnterTime 
= DateTime.Now;
                    
return true;
                }
            }
private void EnterWait(QueueState handler)
            {
                
lock (mWaitHandle)
                {
                    mWaitHandle.Enqueue(handler);
                    
                }
          
            }
            
private Queue<QueueState> mWaitHandle = new Queue<QueueState>();
           
            
public void Exit(string owner)
            {
                
lock (this)
                {
                    
if (owner == SYSTEM_ID)
                    {
                        Owner 
= null;
                        Count 
= 0;
                        
                    }
                    
else
                    {
                        
if (owner == Owner)
                        {
                            Count
--;
                        }
                    }
                    
if (Count == 0)
                    {
                        
lock (mWaitHandle)
                        {
                            
if (mWaitHandle.Count > 0)
                            {
                                QueueState state 
= mWaitHandle.Dequeue();
                                state.Handler.Set();
                            }
                        }
                    }
                    
                 
                }
            }
            
public int EntrerMilliseconds
            {
                
get;
                
set;
            }
            
public DateTime EnterTime
            {
                
get;
                
set;
            }
            
public string ID
            {
                
get;
                
set;
            }
            
public string Owner
            {
                
get;
                
set;
            }
            
public int Count
            {
                
get;
                
set;
            }
            
public void Expires()
            {
                
lock (this)
                {
                    TimeSpan ts 
= DateTime.Now - EnterTime;
                    
if (ts.TotalMilliseconds > EntrerMilliseconds)
                        Exit(SYSTEM_ID);
                }
            }
        }
#region IDisposable 成员
        
private bool mDisposed = false;
        
public void Dispose()
        {
            
lock (this)
            {
                
if (!mDisposed)
                {
                    Exit(mID,mOwnerID);
                    mDisposed 
= true;
                }
            }
           
        }
#endregion
    }
    
class QueueState
    {
        
public QueueState()
        {
            EntrerMilliseconds 
= 60000;
        }
        
public bool Idle
        {
            
get;
            
set;
        }
        
public int EntrerMilliseconds
        {
            
get;
            
set;
        }
        
public int TimeOut
        {
            
get;
            
set;
        }
        
private System.Threading.EventWaitHandle mHandler = new EventWaitHandle(false, EventResetMode.ManualReset);
        
public System.Threading.EventWaitHandle Handler
        {
            
get
            {
                
return mHandler;
            }
            
        }
    }

实现相关锁的WEB服务

    代码

        /// <summary>
        
    /// 对象锁服务
        
    /// </summary>
        [WebService(Namespace = "http://tempuri.org/")]
        [WebServiceBinding(ConformsTo 
    = WsiProfiles.BasicProfile1_1)]
        [System.ComponentModel.ToolboxItem(
    false)]
        
    public class ObjectEnterService : System.Web.Services.WebService
        {

            [WebMethod]

    public string TryEnter(string id, int seconds, int timeout)
            {
                
    string owner = null;
                Core.ObjectEnter.TryEnter(id, seconds 
    * 1000, timeout * 1000, (o, Success) =>
                {
                    
    if(Success)
                        owner 
    = o;
                });
                
    return owner;
            }
            [WebMethod]
            
    public void Exit(string owner, string id)
            {
                Core.ObjectEnter.Exit(owner, id);
            }
        }

     服务比较简单如果能锁住对象就返回一个拥有者的ID,释放的时候需要转入这个拥有者的ID和锁标识.