Mutex对象是通过引用传递的吗?

时间:2011-10-20 11:43:39

标签: c# .net mutex pass-by-reference reference-type

我正在从Class构造几个对象,并使用这些类中的特定函数来启动Threads。现在,包含构造这些对象的成员函数的Class具有静态私有Mutex成员。我将此静态成员传递给构造函数,并在每个构造函数内部,传递的Mutex(可能通过引用)被分配给另一个本地成员。

如果我然后使用这些本地Mutex成员中的每一个来确保线程安全,我能够实现这一目标吗?我指望这个事实,无论存在多少个包含Thread函数的对象的不同实例,因为它们都指向相同的Mutex对象,线程安全性确保正确使用。

请在下面找到代码表示代码段:

Class ThreadClass
{
 private Mutex myCopyOfMutex;
public ThreadClass(Mutex _globalMutex)
{
 myCopyOfMutex = _globalMutex;
}
public ThreadFunction()
{

// Wait until it is safe to enter.
myCopyOfMutex.WaitOne();
// critical code

// Release the Mutex.
 myCopyOfMutex.ReleaseMutex();

}
}

Class MotherClass
{
  private static Mutex mut = new Mutex();

  ThreadClass one = new ThreadClass(mut); // first instance
  Threadclass two = new ThreadClass(mut); // second instance

// Assign the Thread function to run on separate Thread

}

4 个答案:

答案 0 :(得分:3)

是的,它会起作用。不,它不是通过引用传递的。

传递 参考与传递 之间存在重要差异参考

当您将引用类型传递给方法时,它通常作为引用传递

SomeMethod(mutex);

要通过引用传递参数,请使用ref关键字:

SomeMethod(ref mutex);

方法签名中的参数也必须使用ref关键字声明:

public void SomeMethod(ref Mutex mutex) {

通过引用传递变量 意味着您传递对变量的引用,而不是变量中包含的引用的副本。然后,该方法可以更改变量本身,而不仅仅是引用指向的对象。

在大多数情况下,在这种情况下,您应该以常规方式传递参数。只有当您因特定原因需要时,才能通过引用传递

答案 1 :(得分:1)

(答案完全重写,旧答案在底部)

通常,System.Threading.Mutex用于进程间通信。如果您只想在同一个进程中同步线程,那么使用全权重的Mutex是一种过度杀伤力。您可以使用lock运算符的任何对象:

Class ThreadClass
{
    // static is important, this way the object is shared among all
    // class instances
    private static object myMutex = new object();

    public ThreadFunction()
    {
        // Wait until it is safe to enter.
        lock(myMutex)
        {
            // critical code
        }
        // the mutex is automatically released after leaving the block.
    }
}

Class MotherClass
{
    ThreadClass one = new ThreadClass(); // first instance
    Threadclass two = new ThreadClass(); // second instance

    // Assign the Thread function to run on separate Thread
}

lock - 方法的优点是早期返回和异常安全的可能性(想象一下如果关键代码抛出异常会发生什么;但请看Eric Lippert的article about exceptions under lock)。

如果整个方法很关键,并且课程中有不再关键方法,那么您可以更简单地执行此操作:

Class ThreadClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public ThreadFunction()
    {
        // critical code
    }
}

Class MotherClass
{
    ThreadClass one = new ThreadClass(); // first instance
    Threadclass two = new ThreadClass(); // second instance

    // Assign the Thread function to run on separate Thread
}

(旧答案保留在这里是为了保持一致)

所有类实例都通过C#中的引用传递。如果您的互斥锁是一个类(例如,它是System.Threading.Mutex),它将自动通过引用传递。

查看here了解更多信息。


校正:
正如@Guffa正确指出的那样,您不会通过引用传递类实例,而是通过值将引用传递给类实例(如果不使用ref关键字)。为了你的目的,它实际上几乎是一样的。不同之处在于传递的引用中的更改在被调用者之外是不可见的。

答案 2 :(得分:1)

是互斥是通过引用传递的,因为它们是类类型而不是结构类型

答案 3 :(得分:0)

从您的简报中,我假设您正在使用Mutex来同步共享资源访问。

Mutex是一种托管引用类型,它使用Win32中的非托管互斥锁。要回答您的问题,是的,它是参考类型。

但是你的问题让我想到了两点

  1. 为什么你担心参考?
  2. 我的建议是,如果您担心要共享相同的Mutex实例,请继续创建一个名为Mutex(检查Mutex的构造函数重载)。卧底操作系统将确保这个名为Mutex的同步访问。

    1. 为什么您希望Mutex实例是静态的?
    2. 我的建议是,静态变量由JIT在与AppDomain关联的特殊堆中分配。这称为Loader堆。除非您卸载/重新加载AppDomain,否则此加载程序堆永远不会收集垃圾。所以我的观点是,如果你使用Mutex作为静态成员,那么你可能最终会持有很多互斥锁句柄。