C# 互斥量处理

Posted

技术标签:

【中文标题】C# 互斥量处理【英文标题】:C# Mutex handling 【发布时间】:2022-01-14 10:07:37 【问题描述】:

我不确定如何处理互斥锁。 我需要一个进程只运行一次,但如果由于某种原因它意外崩溃或关闭,我还需要重置废弃的互斥锁。

出于这个原因,我进行了一个帮助程序调用,试图获取一个超时的互斥锁(按名称标识)。如果获取互斥锁失败,则返回 NULL,否则返回将由方法调用者处理的互斥锁。 如果互斥体被放弃,我将重置它并将请求视为失败(不是代码被用于周期性过程的问题,如果锁定有时失败,那么过程将恢复到下一次运行)。

我要问的是,是否有一些我没有考虑过的情况可能会给我带来问题

这里是代码:

public class MutexManager

    /// <summary>
    /// Try to acquire a global mutex
    /// </summary>
    /// <param name="mutexName">Mutex unique name</param>
    /// <param name="timeout_ms">Timeout in milliseconds (Optional : default = 5000, if <= 0 no timeout is applied, infinite wait and possibile daeadlock) </param>
    /// <returns>The acquired Mutex or null if Mutex can not be acquired</returns>
    public static Mutex TryRegister(string mutexName, int timeout_ms = 5000)
    
        // unique id for global mutex - Global prefix means it is global to the machine
        string mutexId = string.Format("Global\\0", mutexName);

        bool createdNew;
        var allowEveryoneRule =new MutexAccessRule(    new SecurityIdentifier(WellKnownSidType.WorldSid
                                                       , null)
                                                       , MutexRights.FullControl
                                                       , AccessControlType.Allow
                                                       );
        Mutex mutex = null;
        
            mutex = new Mutex(false, mutexId, out createdNew);
            var hasHandle = false;

            try
            
                hasHandle = mutex.WaitOne(timeout_ms, false);
                if (hasHandle == false)
                    return null;
                else
                    return mutex;
            
            catch (AbandonedMutexException)
            
                mutex.ReleaseMutex();
                mutex.Close();
                mutex.Dispose();
                return null;
            
            catch (Exception err)
            
                return null;
            
        
    

这里我将如何使用上面的类。下面的代码用于周期性过程(通过 Windows 调度程序调度),所以如果有时出现问题不是问题(下一次运行将完成工作),重要的想法是没有竞争条件或死锁

using ( var mutex = MutexManager.TryRegister("procedureName") )

    ...DO WORK

【问题讨论】:

【参考方案1】:

互斥锁由单个进程“拥有”,如果进程崩溃或关闭,互斥锁将被释放。

如果进程崩溃并且 Mutex 被释放,那么它被认为是“已放弃”,这是一种表明原始进程不再拥有它的信号 - 但也没有明确释放它。

我对您的问题或代码不太了解的是对废弃互斥体的处理。如果之前没有放弃,助手只会返回一个互斥锁。如果它被放弃,代码会成功检索 Mutex,然后释放它并返回,而根本不提供 Mutex。

这可能是意图,但根据问题的措辞有点难以理解。如果帮助程序打算重置返回 Mutex,那么 AbandonedMutexException 的处理看起来不正确,因为它总是返回 null。

【讨论】:

抱歉我的英语不好(不是我的母语)。是的,在放弃互斥锁的情况下,我的意图是丢弃被放弃的互斥锁并错过执行。因为代码是定期执行的,所以我更喜欢等待下一个计划并在“celan”情况下工作,希望能澄清我的意图。 "如果进程崩溃并且 Mutex 被释放,那么它被认为是 "Abandoned""。 - 不应该是“如果拥有互斥锁的进程崩溃了,那么它就被认为是“被遗弃的””?

以上是关于C# 互斥量处理的主要内容,如果未能解决你的问题,请参考以下文章

多线程面试题系列(15):关键段,事件,互斥量,信号量的“遗弃”问题

21.互斥量

互斥量和二进制信号量之间的实际区别

(转载)pThreads线程 线程同步--互斥量/锁

提高互斥量和类成员访问

RT-Thread快速入门-互斥量