【问题标题】:Usage of Mutex in c#C#中互斥锁的使用
【发布时间】:2011-08-10 22:11:31
【问题描述】:

我在 c# 和一般情况下的线程方面有点新意, 在我的程序中,我使用mutex 只允许 1 个线程进入关键部分,并且由于未知原因进行一些 cw 打印,我可以看到超过 1 个线程进入我的关键部分,这是我的代码:

Mutex m = new Mutex();
m.WaitOne();
<C.S> // critical section here
m.ReleaseMutex();

我非常想知道我是否在这里做错了,提前感谢您的帮助。

编辑:

我的代码包含类,所以基本上看起来更像这样:

public class test
{
    private mutex m;
    public test()
    {
         m = new mutex();
    }
    public func()
    {
         m.WaitOne();
         <C.S> // critical section here
         m.ReleaseMutex();
     }


    } 

【问题讨论】:

  • 您必须拥有多个该类的实例。
  • 即实例级互斥锁;您确定您的编码不在单独的不相关实例的关键部分吗?此外,任何错误都会导致代码永久锁定 - 您需要 try/finally 以确保安全。
  • 编辑后:此 Mutex 仅在对象级别起作用,即 1 个 CrtentialSection / 实例。这就是你想要的吗?
  • 信息:Mutexmutual exclusion

标签: c# multithreading mutex


【解决方案1】:

这里的问题是你所有的调用者都在使用一个不同的互斥体;您需要将锁定对象共享,通常是通过将其设为字段。例如,切换到更简单的lock 隐喻:

private readonly object syncLock = new object();
public void ThreadSafeMethod() {
    lock(syncLock) {
        /* critical code */
    }
}

或使用互斥锁:

private readonly Mutex m = new Mutex();
public void ThreadSafeMethod() {
    m.WaitOne();
    try {
        /* critical code */
    } finally {
        m.ReleaseMutex();
    }
}

【讨论】:

  • 我使用的互斥锁是一个类的全局互斥锁,所以我认为它是同一个互斥锁
  • @Nadav - 这不是您的问题所显示的内容......您的问题将其显示为与代码相同的位置,即局部变量。
  • Nadav - 你确定你没有超过一个类的实例吗?几乎所有的“锁定/互斥体让多个调用通过”问题都证明是锁定/互斥体对象比您预期的要多。
【解决方案2】:

看起来你给每个线程一个自己的互斥锁。那是行不通的。

在大多数情况下,互斥锁是矫枉过正的。你只需要:

private static object syncLock = new object();  // just 1 instance

....

lock(syncLock)
{
    // critical section
}

【讨论】:

  • 我不确定我们是否可以推断出static 是有意为之的……尽管我们也无法推断出它不是;p
  • @Marc,正确。我使用静态作为我认为的对立面是错误。代码不完全清楚。
【解决方案3】:

这种模式根本没有锁定。每个线程创建一个新的 Mutex 对象并立即拥有它的锁。其他线程自己创建和使用新的 Mutex。

考虑使用常规的 lock()!

lock(_lockobject) {
   // do inside what needs to be done - executed on a single thread only
} 

其中 _lockobject 是类中的一个简单私有变量:

private object _lockobject; 

编辑:感谢评论者!存在一些情况,其中 lock(this) 可能很危险。所以我删除了那个。

【讨论】:

  • 不要lock(this),或lock(someType),或lock(anyString) - 这些都是糟糕的设计,不健壮。
  • 顺便说一句,锁定这并不是一个好主意,更好的是创建对象类型的简单变量toolazy.me.uk/…
  • lock(this) 不被认为是好的做法。 (参见,例如haacked.com/archive/2006/08/08/ThreadingNeverLockThisRedux.aspx)。制作一个仅用于锁定的对象要好得多,而忘记了曾经犯过让任何对象都被锁定的 .NET 设计错误。
  • @WillDean - 确实;我宁愿有一个特定的类型,例如Monitor 实例。另外,object 应该是 abstract ;p
【解决方案4】:

Mutex 用于识别运行的应用实例。

 using (Mutex mutex = new Mutex(true, "app name", out createdNew))
            {
                if (createdNew)//check app is already run
                {
                    KillOthers();
                    StartApp();
                }
                else
                {
                    MessageBox.Show("Another instance already running!");
                }
            }

【讨论】:

    【解决方案5】:

    我可以对已接受的答案进行更正吗?

    private readonly Mutex m = new Mutex();
    public void ThreadSafeMethod() {
        while(!m.WaitOne()){}
        try {
            /* critical code */
        } finally {
            m.ReleaseMutex();
        }
    }
    

    【讨论】:

    • 嗨,伊曼纽尔。为什么你认为你的答案是一种改进?循环:while (!m.WaitOne()) { } 永远不会运行多次,因为没有参数的 WaitOne 方法总是返回 true(除非它永远不会返回)。
    猜你喜欢
    • 1970-01-01
    • 2022-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2011-01-21
    相关资源
    最近更新 更多