【问题标题】:Can I create a prioritized synchronization lock with C#我可以用 C# 创建一个优先同步锁吗
【发布时间】:2013-05-27 19:42:04
【问题描述】:

我目前正在使用Mutex 在进程之间建立对文件的同步访问:

//Process 1
//High frequency "writes"
try
{
    mutex.WaitOne(System.Threading.Timeout.Infinite);

    try
    {
        //Do write operation

    }
    finally
    {
        mutex.ReleaseMutex();
    }
}
catch(AbandonedMutexException)
{
    //Log error
}

然后有时我可能需要检查已写入文件的内容:

//Process 2
//Low frequency "reads"
try
{
    mutex.WaitOne(System.Threading.Timeout.Infinite);

    try
    {
        //Do read operation

    }
    finally
    {
        mutex.ReleaseMutex();
    }
}
catch(AbandonedMutexException)
{
    //Log error
}

但是使用这种技术会发生什么,正在执行低频“读取”的Process 2 似乎挂起并且永远不会接收到对资源的​​访问,或者这样做可能需要很长时间。

在我的情况下有更好的锁吗?

PS。它必须兼容才能在进程之间使用。

【问题讨论】:

    标签: c# .net synchronization locking ipc


    【解决方案1】:

    我想我通过引入一个事件来解决它:

    EventWaitHandle event = new EventWaitHandle(true, 
         EventResetMode.ManualReset, 
         strEventGlobalName,     //Must be the same for each process
         out dummy, 
         eventSecurity);         //To allow access between processes
    

    所以作者看起来是这样的:

    //Process 1
    //High frequency "writes"
    
    //Wait to allow writing
    if (event.WaitOne(System.Threading.Timeout.Infinite))
    {
        try
        {
            mutex.WaitOne(System.Threading.Timeout.Infinite);
    
            try
            {
                //Do write operation
    
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        catch(AbandonedMutexException)
        {
            //Log error
        }
    }
    

    和这样的读者:

    //Process 2
    //Low frequency "reads"
    
    try
    {
        //Reset event to halt writing
        if (!event.Reset())
            throw new Exception("Did not reset event");
    
        try
        {
            mutex.WaitOne(System.Threading.Timeout.Infinite);
    
            try
            {
                //Do read operation
    
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        catch(AbandonedMutexException)
        {
            //Log error
        }
    }
    finally
    {
        //Set event to allow back writing
        if(!event.Set())
            throw new Exception("Did not set event");
    }
    

    【讨论】:

      【解决方案2】:

      你在使用这样的命名互斥体吗?:

      bool created = false;       
      string mutexHandle = "SOME_UNIQUE_ENOUGH_STRING_slkuhfwer7487rctcwf6gt86efcwwgsa";
      var myFileLock = new Mutex(true, mutexHandle, out created);
      

      因为只有命名的 Mutex 可用于在系统级别的进程之间同步任务。

      如果是这样,您做的是正确的事情(技术上)。

      但是如果你在一端执行高频操作;您应该在 writer 中的 mutex.WaitOne(System.Threading.Timeout.Infinite); 之前提供一个像 Thread.Sleep(1); 这样的空白(例如);或者您应该使用另一种方法,例如内存映射文件,或写入新的标记文件(通过在名称中提供时间戳并删除读取的文件)或使用为您的文件提供版本控制的工具。

      【讨论】:

      • 不,这是一个糟糕的方法。无需“减慢”一个线程/进程即可使其工作。
      • 我并没有说这是一个坏方法。而且由于我们在系统级别没有像“ReaderWriterLock”这样的东西(顺便说一句,ReaderWriterLock 确实有利于写操作而不是读操作);通过添加“放慢速度”,我们为读者提供了一个机会。这不仅仅是锁定。也许应该在每次写入时将更多数据刷新到文件中,而不是多次写入许多微小数据。如果我们想真正深入优化它,那么我们应该为数据库编写一个(微小的)持久层;例如考虑硬盘的“pagesize”之类的! :)
      猜你喜欢
      • 1970-01-01
      • 2011-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      相关资源
      最近更新 更多