In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "how to use the mutex Mutex class of c #". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to use the mutex Mutex class of c #.
What is Mutex?
"mutex" is an abbreviated form of the term "mutually exclusive", that is, mutually exclusive quantities. Mutexes are similar to the Monitor mentioned in the critical section. Only threads with mutexes have access to resources. Since there is only one mutex, it determines that this shared resource will not be accessed by multiple threads at the same time. The thread that currently occupies the resource should hand over the mutex after the task is processed so that other threads can access the resource after obtaining it. Mutexes are more complex than critical areas, because using mutexes not only enables secure sharing of resources in different threads of the same application, but also securely shares resources between threads of different applications.
The mutex in .net is represented by the Mutex class.
Take a short detour first.
Before we start to figure out how to use Mutex, we have to make a short detour and come back.
When you are reading, you should be in the "operating system" when you come into contact with mutex and semaphores. So, in fact, the reason for the emergence of these things is as an OS function. Take a look at Mutex's statement:
[ComVisibleAttribute (true)] public sealed class Mutex: WaitHandle
There is an attribute on the class: ComVisibleAttribute (true), which indicates that the class member is exposed to the COM member. Leave it alone, as long as you know that this thing has something to do with COM, it probably has a close relationship with Windows.
Mutex it has a parent class: WaitHandle
So we had to go a little further and take a look at WaitHandel's statement:
[ComVisibleAttribute (true)] public abstract class WaitHandle: MarshalByRefObject, IDisposable
WaitHandle implements an interface and inherits a parent class. Look at its parent class, MarshalByRefObject:
MarshalByRefObject class
Allows access to objects across application domain boundaries in applications that support remoting.
Note:
An application domain is a partition where one or more applications reside in an operating system process. Objects in the same application domain communicate directly. Objects in different application domains can communicate in two ways: one is to transfer copies of objects across application domain boundaries, and the other is to use agents to exchange messages.
MarshalByRefObject is the base class for objects that communicate across application domain boundaries by using agents to exchange messages.
Well, you don't have to read the rest of the content, otherwise it will go too far. We now know that Mutex is a subclass of WaitHandle (secretly, so are the EventWaitHandle and semaphore Semaphore to be mentioned in the future, and AutoResetEvent and ManualResetEvent are its grandchildren), and WaitHandle inherits from the MarshalByRefObject class that has the ability to cross application domain boundaries in the operating system. So now we can come to some conclusions:
Mutex is a class that encapsulates Win32 API, which invokes some of the operating system's "corresponding" functions more directly; Monitor does not inherit from any parent class and is relatively "native" to .net itself (of course, .net ultimately depends on runtime calls to the operating system's various API). Compared to Monitor, you can think of the Mutex approximation as a shell of the Win32 mutex API.
Mutex is cross-application / application domain, so it can be used for application domain / application communication and mutual exclusion; Monitor, as we have seen so far, can only communicate between threads within the application. In fact, locking can also be provided in multiple application domains if the object used for the lock is derived from MarshalByRefObject,Monitor.
Because Mutex needs to call operating system resources, it is much more expensive to execute than Monitor, so if you only need to synchronize operations between threads within the application, Monitor/lock should be the first choice.
Kind of like Monitor? Let's think of it as lock.
All right, it's back at last. Let's see how to use Mutex.
WaitOne () / WaitOne (Int32, Boolean) / WaitOne (TimeSpan, Boolean): request ownership, which blocks until the current mutex receives a signal, or until an optional timeout interval is reached. These methods look similar to the Wait () method on Monitor and its overloading, except that they do not need to provide a locked object as a parameter. But don't get me wrong, WaitOne () is essentially equivalent to Monitor.Enter () / TryEnter (), not Monitor.Wait ()! This is because the WaitOne () has no way to release the current Mutex like Monitor.Wait () after gaining control, and then block itself.
ReleaseMutex (): releases the current Mutex once. Note that this is emphasized here, because threads with mutexes can repeatedly call Wait series functions without blocking their execution; this is the same as Monitor's Enter () / Exit () can be called repeatedly after acquiring the object lock. The number of times Mutex is called is saved by the common language runtime (CLR), counting + 1 per WaitOne () and-1 per ReleaseMutex (). As long as this count is not 0, other Mutex waiters will think that the Mutex has not been released and there is no way to get the Mutex. In addition, like Monitor.Exit (), only the owner of Mutex can RleaseMutex (), otherwise an exception will be thrown.
If a thread terminates when it has a mutex, we call the mutex Abandoned. In MSDN, Microsoft warned that this was a "serious" programming error. This means that after the owner of the mutex takes ownership, the number of WaitOne () and RelaseMutex () is not equal, and the caller stops irresponsibly, resulting in an inconsistent state of the resources that mutex is protecting. In fact, this is nothing more than a reminder to remember to use Mutex in your try/finally structure.
Since these two functions are not equivalent to Wait () and Pulse () of Monitor, the ReleaseMutex () and WaitOne () methods Mutex cannot be applied to our example.
Of course, there are other methods for synchronous notifications on Mutext, but they are static methods on their parent class, WaitHandle. So they are not "tailor-made" for Mutex, and are a bit out of tune with the way Mutex uses them (you can try to replace Monitor with Mutex to implement our previous scenario), or Mutex is actually somewhat reluctant to own these methods. We will discuss the issue of Mutex and notification in more depth in the next Blog on EventWaitHandle. Let's simply use the example on MSDN to illustrate the simplest application scenario of Mutex:
/ / This example shows how a Mutex is used to synchronize access// to a protected resource. Unlike Monitor, Mutex can be used with// WaitHandle.WaitAll and WaitAny, and can be passed across// AppDomain boundaries.using System;using System.Threading;class Test {/ / Create a new Mutex. The creating thread does not own the / / Mutex. Private static Mutex mut = new Mutex (); private const int numIterations = 1; private const int numThreads = 3; static void Main () {/ / Create the threads that will use the protected resource. For (int I = 0; I
< numThreads; i++) { Thread myThread = new Thread(new ThreadStart(MyThreadProc)); myThread.Name = String.Format("Thread{0}", i + 1); myThread.Start(); } // The main thread exits, but the application continues to // run until all foreground threads have exited. } private static void MyThreadProc() { for(int i = 0; i < numIterations; i++) { UseResource(); } } // This method represents a resource that must be synchronized // so that only one thread at a time can enter. private static void UseResource() { // Wait until it is safe to enter. mut.WaitOne(); Console.WriteLine("{0} has entered the protected area", Thread.CurrentThread.Name); // Place code to access non-reentrant resources here. // Simulate some work. Thread.Sleep(500); Console.WriteLine("{0} is leaving the protected area\r\n", Thread.CurrentThread.Name); // Release the Mutex. mut.ReleaseMutex(); }} 虽然这只是一个示意性的实例,但是我仍然不得不因为这个示例中没有使用try/finally来保证ReleaseMutex的执行而表示对微软的鄙视。对于一个初学的人来说,第一个看到的例子可能会永远影响这个人使用的习惯,所以是否在简单示意的同时,也能"简单地"给大家show一段足够规范的代码?更何况有相当部分的人都是直接copy sample code……一边告诫所有人Abandoned Mutexes的危害,一边又给出一段一个异常就可以轻易引发这种错误的sample,MSDN不可细看。 我不得不说Mutex的作用于其说象Monitor不如说象lock,因为它只有等效于Monitro.Enter()/Exit()的作用,不同之处在于Mutex请求的锁就是它自己。正因为如此,Mutex是可以也是必须(否则哪来的锁?)被实例化的,而不象Monitor是个Static类,不能有自己的实例。 全局和局部的Mutex 如果在一个应用程序域内使用Mutex,当然不如直接使用Monitor/lock更为合适,因为前面已经提到Mutex需要更大的开销而执行较慢。不过Mutex毕竟不是Monitor/lock,它生来应用的场景就应该是用于进程间同步的。 除了在上面示例代码中没有参数的构造函数外,Mutex还可以被其它的构造函数所创建: Mutex():用无参数的构造函数得到的Mutex没有任何名称,而进程间无法通过变量的形式共享数据,所以没有名称的Mutex也叫做局部(Local)Mutex。另外,这样创建出的Mutex,创建者对这个实例并没有拥有权,仍然需要调用WaitOne()去请求所有权。 Mutex(Boolean initiallyOwned):与上面的构造函数一样,它只能创建没有名称的局部Mutex,无法用于进程间的同步。Boolean参数用于指定在创建者创建Mutex后,是否立刻获得拥有权,因此Mutex(false)等效于Mutex()。 Mutex(Boolean initiallyOwned, String name):在这个构造函数里我们除了能指定是否在创建后获得初始拥有权外,还可以为这个Mutex取一个名字。只有这种命名的Mutex才可以被其它应用程序域中的程序所使用,因此这种Mutex也叫做全局(Global)Mutex。如果String为null或者空字符串,那么这等同于创建一个未命名的Mutex。因为可能有其他程序先于你创建了同名的Mutex,因此返回的Mutex实例可能只是指向了同名的Mutex而已。但是,这个构造函数并没有任何机制告诉我们这个情况。因此,如果要创建一个命名的Mutex,并且期望知道这个Mutex是否由你创建,最好使用下面两个构造函数中的任意一个。最后,请注意name是大小写敏感的。 Mutex(Boolean initiallyOwned, String name, out Boolean createdNew):头两个参数与上面的构造函数相同,第三个out参数用于表明是否获得了初始的拥有权。这个构造函数应该是我们在实际中使用较多的。 Mutex(Boolean initiallyOwned, String name, out Booldan createdNew, MutexSecurity):多出来的这个MutexSecurity参数,也是由于全局Mutex的特性所决定的。因为可以在操作系统范围内被访问,因此它引发了关于访问权的安全问题,比如哪个Windows账户运行的程序可以访问这个Mutex,是否可以修改这个Mutext等等。关于Mutex安全性的问题,这里并不打算仔细介绍了,看看这里应该很容易明白。 另外,Mutex还有两个重载的OpenExisting()方法可以打开已经存在的Mutex。 Mutex的用途 如前所述,Mutex并不适合于有相互消息通知的同步;另一方面而我们也多次提到局部Mutex应该被Monitor/lock所取代;而跨应用程序的、相互消息通知的同步由将在后面讲到的EventWaiteHandle/AutoResetEvent/ManualResetEvent承担更合适。所以,Mutex在.net中应用的场景似乎不多。不过,Mutex有个最常见的用途:用于控制一个应用程序只能有一个实例运行。 using System;using System.Threading;class MutexSample{ private static Mutex mutex = null; //设为Static成员,是为了在整个程序生命周期内持有Mutex static void Main() { bool firstInstance; mutex = new Mutex(true, @"Global\MutexSampleApp", out firstInstance); try { if (!firstInstance) { Console.WriteLine ("已有实例运行,输入回车退出……"); Console.ReadLine(); return; } else { Console.WriteLine ("我们是第一个实例!"); for (int i=60; i >0;-- I) {Console.WriteLine (I); Thread.Sleep (1000);} finally {/ / only the first instance gets control, so ReleaseMutex is needed only in this case, otherwise an exception will be thrown. If (firstInstance) {mutex.ReleaseMutex ();} mutex.Close (); mutex = null;}
This is a console program, you can try to run more than one program at a time after compilation, and of course only one program is counting down. You may find other ways to implement application singletons on the Internet, such as using Process to find process names, Win32 API findwindow to find forms, and so on, but these methods do not guarantee absolute singletons. Because multiprocess and multithreading are the same, due to the random allocation of CPU time slices, it is possible for multiple processes to check that no other instances are running at the same time. This is easy to happen when CPU is busy, such as Aoyou browser. Even if you set up to allow only one instance to run, when the system is busy, as long as you try to open the browser several times, you may be "lucky" to open several separate browser windows.
Don't forget that to implement a singleton of an application, you need to maintain Mutex throughout the run of the application, not just in the initial phase of the program. So, in the example, the establishment and destruction code of Mutex wraps the entire Main () function.
Two details to pay attention to when using Mutex
You may have noticed that in the example, a "Global\" prefix is given in the string named Mutex. This is because the named global mutex has two kinds of visibility on the server running Terminal Services (or remote Desktop). If the name starts with the prefix "Global\", mutex is visible in all Terminal Server sessions. If the name starts with the prefix "Local\", the mutex is visible only in the terminal server session in which it was created, in which case there can be a separate mutex with the same name in every other terminal server session on the server. If you create a named mutex without a prefix, it takes the prefix "Local\". In a terminal server session, two mutex with different name prefixes are independent mutex, and the two mutex are visible to all processes in the terminal server session. That is, the prefix names "Global\" and "Local\" are only used to indicate the scope of the mutex name relative to the terminal server session, not to the process. Finally, note that "Global\" and "Local\" are case-sensitive.
Since the parent class implements the IDisposalble interface, this class must require you to manually release unmanaged resources. So you have to use try/finally, or the using I hate, and call the Close () method to release all the resources consumed by Mutex!
At this point, I believe you have a deeper understanding of "how to use the mutex Mutex class of c #". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.