我正在从一个类构造多个对象,并使用这些类中的特定函数来启动线程。现在,包含构造这些对象的成员函数的类具有静态私有互斥体成员。我将此静态成员传递给构造函数,并且在每个构造函数内,传递的互斥体(大概是通过引用)被分配给另一个本地成员。
如果我然后使用每个本地互斥成员来确保线程安全,我能够实现这一目标吗?我认为,无论存在多少个包含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
}
I am constructing several objects from a Class and using a particular function from these classes to start Threads. Now the Class containing the member function from where these objects are constructed, has a static private Mutex member. I am passing this static member to the constructors and inside each constructor, the passed Mutex(presumably by reference) is assigned to another local member.
If I then use each of these local Mutex member to ensure Thread safety, will I be able to achieve this? I am counting on the fact, no matter how many different instances of the object containing the Thread function exists, since they are all referring to the same Mutex object, Thread safety is ensure if properly used.
Please find below code snippet to represent the Idea:
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)
是的,它会起作用。不,它不是通过引用传递的。
传递a引用和传递by之间存在重要区别参考。
当您将引用类型传递给方法时,它通常作为引用传递:
要通过引用传递参数,可以使用
ref
关键字:方法签名中的参数也必须使用
ref
关键字声明:通过引用传递变量意味着您传递对该变量的引用,而不是该变量的副本变量中包含的引用。然后,该方法可以更改变量本身,而不仅仅是引用指向的对象。
在大多数情况下,在这种情况下,您应该以常规方式传递参数。仅当您出于特定原因需要时才通过引用传递。
Yes, it will work. No, it's not passed by reference.
There is an important difference between passing a reference and passing by reference.
When you pass a reference type to a method, it's normally passed as a reference:
To pass a parameter by reference, you use the
ref
keyword:The parameter in the method signature also has to be declared using the
ref
keyword:Passing a variable by reference means that you pass a reference to the variable, not a copy of the reference that is contained in the variable. The method can then change the variable itself, not only the object that the reference points to.
In most cases, and also in this case, you should pass parameters in the regular way. Passing by reference is only done when you need it for a specific reason.
yes mutex are passed by reference as they are class type not the struct type
(答案完全重写,旧答案在底部)
通常,System.Threading.Mutex用于进程间通信。如果您只想同步同一进程中的线程,那么使用全权重互斥量就有点大材小用了。您可以将任何对象与
lock
运算符一起使用:lock
方法的优点是可以提前返回和异常安全(想象一下如果关键代码抛出异常会发生什么) ;但是看看 Eric Lippert 的 有关锁定下异常的文章)。如果整个方法是关键的,并且类中没有不再关键方法,你可以做得更简单:(
为了保持一致性,旧的答案保留在这里)
所有类C# 中的实例通过引用传递。如果您的互斥锁是一个类(例如,它是
System .Threading.Mutex
),它将自动通过引用传递。有关详细信息,请参阅此处。
更正:
正如@Guffa正确指出的那样,您不通过引用传递类实例,而是通过值传递对类实例的引用(如果不使用
ref
关键字)。对于你的目的来说,实际上几乎是一样的。不同之处在于传递的引用中的更改在被调用者外部不可见。(Answer completely rewritten, the old answer is at the bottom)
Usually, System.Threading.Mutex is used for interprocess communication. If you just want to synchronize your threads within the same process, using a full-weight Mutex is an overkill. You can use any object with a
lock
operator:The advantage of
lock
-approach is the possibility of early returns and exception safety (imagine what happens if the critical code throws an exception; but look at Eric Lippert's article about exceptions under lock).If the whole method is critical, and there are no more critical methods in the class, you can do it even simpler:
(Old answer is kept here for consistency)
All class instances are passed by reference in C#. If your Mutex is a class (for example, it's
System.Threading.Mutex
), it will automatically be passed by reference.Look here for more info.
Correction:
As @Guffa correctly states, you don't pass a class instance by reference, but a reference to a class instance by value (if not using
ref
keyword). For your purpose, it's almost the same, actually. The difference is that the changes in the passed reference are not visible outside the callee.根据您的介绍,我假设您正在使用互斥体来同步共享资源访问。
互斥体是一种托管引用类型,它实际上使用了 Win32 中的非托管互斥体。回答你的问题,是的,它是一个参考类型。
但你的问题让我想到两点:
我的建议是,如果您担心共享相同的互斥体实例,那么请继续创建一个命名互斥体(检查互斥体的构造函数重载)。 Undercover 操作系统将确保对这个名为 Mutex 的同步访问。
我的建议是,静态变量由 JIT 分配在与 AppDomain 关联的特殊堆中。这称为装载机堆。除非您卸载/重新加载 AppDomain,否则该加载程序堆永远不会被垃圾回收。所以我的观点是,如果您使用互斥体作为静态成员,那么您最终可能会持有大量互斥体句柄。
From your briefing, I assume you are using Mutex to synchronize shared resource access.
Mutex is a managed reference type which under cover uses unmanaged mutex from Win32. To answer your question, Yes it is a reference type.
But your question leads me to think two points
My advice is that, If you are worried about same Mutex instance to be shared then go ahead and create a named Mutex ( check the constructor overload for Mutex). Undercover operating system will ensure the synchronized access for this named Mutex.
My advice here is that, static variables are allocated by the JIT in special heap associated with the AppDomain. This is called Loader heap. This loader heap never get garbage collected unless you unload/reload AppDomain. So my point here is that, if you are using Mutex as static member then you likely to end up holding lot of mutex handles.