Maison  >  Article  >  développement back-end  >  Explication détaillée de la synchronisation .NET et du Mutex asynchrone

Explication détaillée de la synchronisation .NET et du Mutex asynchrone

迷茫
迷茫original
2017-03-26 16:10:262452parcourir

Cet essai continue : Synchronisation .NET et collection thread-safe asynchrone (11)

Cet essai et les deux essais suivants présenteront la dernière partie majeure de la série de points de connaissances sur la synchronisation .NET et les blocs asynchrones. : Famille WaitHandle.

Classe de base abstraite : WaitHandle, trois sous-classes : EventWaitHandle (notification d'événement), Mutex (verrouillage de synchronisation de processus), Semaphone (sémaphore) et deux petits-enfants : System.Threading.AutoResetEvent, System Threading.ManualResetEvent. sous-classes de EventWaitHandle.

1. Classe de base abstraite WaitHandle

[ComVisibleAttribute(true)]public abstract class WaitHandle : MarshalByRefObject, IDisposable

Grâce aux informations ci-dessus, nous pouvons savoir que WaitHandle hérite de MarshalByRefObject et implémente l'interface IDisposable.

Vous n'êtes peut-être pas très familier avec MarshalByRefObject, mais vous aurez certainement utilisé plusieurs de ses sous-classes. Laissez-nous vous révéler son vrai visage.

MarshalByRefObject est décrit dans MSND comme suit :

Le domaine d'application est une partition où une ou plusieurs applications résident dans un processus du système d'exploitation. Les objets d'un même domaine d'application communiquent directement. Les objets de différents domaines d'application peuvent communiquer de deux manières : en transférant des copies d'objets au-delà des limites du domaine d'application ou en utilisant des proxys pour échanger des messages. MarshalByRefObject est une classe de base pour les objets qui communiquent au-delà des limites du domaine d'application en échangeant des messages à l'aide de proxys.

Vous pourriez être encore plus confus après avoir vu ceci. L'ai-je utilisé ? Vous avez utilisé ses sous-classes ? C'est vrai, ses sous-classes ont été utilisées, et il y en a bien d'autres.

Par exemple, Brush, Image, Pen, Font, etc. dans l'espace de noms System.Drawing, et il existe également le Stream plus familier sous l'espace de noms System.IO.

Lecture approfondie : Utilisez MarshalByRefObject implémente AOP.

Voyant cela, il nous suffit de savoir que WaitHandle a la capacité de communiquer entre les domaines d'application.

2. Mutex (verrouillage de synchronisation des processus)

1. MSDN définit Mutex comme la primitive de synchronisation entre les processus, c'est-à-dire le concept de verrouillage.

D'un autre côté, Monitor n'est généralement utilisé que pour communiquer entre les threads du domaine d'application. En fait, Monitor peut également fournir un verrouillage dans plusieurs domaines d'application si l'objet utilisé pour le verrouillage est dérivé de MarshalByRefObject.

Étant donné que Mutex doit appeler les ressources du système d'exploitation, sa surcharge d'exécution est bien supérieure à celle de Monitor. Par conséquent, si vous avez uniquement besoin de synchroniser les opérations entre les threads au sein de l'application, Monitor/lock devrait être le premier choix

.

2. Utilisation du Mutex

  • WaitOne() /WaitOne(TimeSpan, Boolean) et plusieurs surcharges : demande de propriété, cet appel se bloquera jusqu'à ce que le mutex actuel reçoive un signal, ou jusqu'à ce que lorsque l'intervalle de délai d'attente facultatif soit atteint, aucune de ces méthodes n'a besoin de fournir un objet de verrouillage comme paramètre supplémentaire.

    • Vous pouvez utiliser la méthode WaitHandle.WaitOne pour demander la propriété d'un mutex. Le fil appelant est bloqué jusqu'à ce que l'un des événements suivants se produise :

    • Le mutex signale la non-propriété. Dans ce cas, la méthode WaitOne renverra true, prenant la propriété mutex du thread appelant et accédant à la ressource protégée par le mutex. Une fois que le thread a fini d'accéder aux ressources, la méthode ReleaseMutex doit être appelée pour libérer la propriété du mutex.

    • a la méthode millisecondsTimeout ou le paramètre timeout est passé . Dans ce cas, la méthode WaitOne renverra false et le thread ne prendra pas possession du mutex pour le moment.

  • ReleaseMutex() : Libère le Mutex actuel une fois. Notez que cela est souligné une fois, car le thread qui possède le mutex peut appeler à plusieurs reprises la série de fonctions WaitOne sans bloquer son exécution ; ceci et Enter()/Exit() du moniteur peuvent être appelés à plusieurs reprises après avoir acquis le verrou d'objet. Le nombre de fois que Mutex est appelé est enregistré par le Common Language Runtime (CLR). Le nombre est de +1 pour chaque WaitOne() et de -1 pour chaque ReleaseMutex(). Tant que ce nombre n'est pas 0, les autres serveurs Mutex le feront. considérez ce Mutex S'il n'est pas publié, il n'y a aucun moyen d'obtenir le Mutex. De plus, comme Monitor.Exit(), seul le propriétaire du Mutex peut RleaseMutex(), sinon une exception sera levée.

  • Si le thread se termine alors que vous possédez le mutex, nous disons que le mutex est abandonné. Dans MSDN, Microsoft prévient qu'il s'agit d'une erreur de programmation « grave ». Cela signifie qu'une fois que le propriétaire du mutex en a obtenu la propriété, le nombre de WaitOne() et ReleaseMutex() est inégal et l'appelant lui-même se termine de manière irresponsable, ce qui entraîne la ressource protégée par le mutex dans un état incohérent. En fait, ce n'est rien de plus qu'un rappel de n'oubliez pas d'utiliser Mutex dans la structure try/finally.

3、全局和局部的Mutex

如果在一个应用程序域内使用Mutex,当然不如直接使用Monitor/lock更为合适,因为前面已经提到Mutex需要更大的开销而执行较慢。不过Mutex毕竟不是Monitor/lock,它生来应用的场景就应该是用于进程间同步的。用于在进程间通讯的Mutex我们称为全局Mutex,而只用于在应用程序域内部通讯的Mutex、我们称为局部Mutex.

全局Mutex和局部Mutex是通过构造函数来构造不同的实例的,让我们来看一下Mutex的构造函数,一共有5个,挑两个具有代表性的看一下吧:

  • Mutex():用无参数的构造函数得到的Mutex没有任何名称,而进程间无法通过变量的形式共享数据,所以没有名称的Mutex也叫做局部(Local)Mutex。另外,这样创建出的Mutex,创建者对这个实例并没有拥有权,仍然需要调用WaitOne()去请求所有权。

  • Mutex(Boolean initiallyOwned, String name, out Booldan createdNew, MutexSecurity):第一个bool参数:指示初始化的实例是否拥有互斥体所有权。第二个string类型、为互斥体指定一个名称,如果string为null或者空字符串 则相当于创建一个没有名字的Mutex,当属于局部Mutex. 而有名字的Mutex当属于全局Mutex.第三个bool参数、如果已经初始化了互斥体 返回True, 如果互斥体已经存在则返回False. 最后一个参数用于Mutex访问的安全性控制。

4、用途 

Mutex天生为进程间的同步基元,因此它可以用来控制应用程序的单实例

/// <summary>/// 单实例运行/// </summary>/// <returns> true 应用程序已启动,false 则没有 
</returns>public bool SingleRun(ref System.Threading.Mutex mutex )
{
    mutex = new System.Threading.Mutex(false, "WINDOWS");    
    if (!mutex.WaitOne(0, false))
    {
        mutex.Close();
        mutex = null;
    }    if (mutex == null)
    {        return true;
    }    return false;
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn