Partager via


Mutex Classe

Définition

Primitive de synchronisation qui peut également être utilisée pour la synchronisation entre processus.

public ref class Mutex sealed : System::Threading::WaitHandle
public sealed class Mutex : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Mutex : System.Threading.WaitHandle
type Mutex = class
    inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(true)>]
type Mutex = class
    inherit WaitHandle
Public NotInheritable Class Mutex
Inherits WaitHandle
Héritage
Héritage
Attributs

Exemples

Cet exemple montre comment un objet local Mutex est utilisé pour synchroniser l’accès à une ressource protégée. Étant donné que chaque thread appelant est bloqué jusqu’à ce qu’il acquière la propriété du mutex, il doit appeler la ReleaseMutex méthode pour libérer la propriété du mutex.

using System;
using System.Threading;

class Example
{
    // 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 newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        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.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name);
        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", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
        Console.WriteLine("{0} has released the mutex", 
            Thread.CurrentThread.Name);
    }
}
// The example displays output like the following:
//       Thread1 is requesting the mutex
//       Thread2 is requesting the mutex
//       Thread1 has entered the protected area
//       Thread3 is requesting the mutex
//       Thread1 is leaving the protected area
//       Thread1 has released the mutex
//       Thread3 has entered the protected area
//       Thread3 is leaving the protected area
//       Thread3 has released the mutex
//       Thread2 has entered the protected area
//       Thread2 is leaving the protected area
//       Thread2 has released the mutex
Imports System.Threading

Module Example
   ' Create a new Mutex. The creating thread does not own the mutex.
   Private mut As New Mutex()
   Private Const numIterations As Integer = 1
   Private Const numThreads As Integer = 3
   
   Public Sub Main()
        ' Create the threads that will use the protected resource.
        For i As Integer = 0 To numThreads - 1
            Dim newThread As New Thread(AddressOf ThreadProc)
            newThread.Name = String.Format("Thread{0}", i + 1)
            newThread.Start()
        Next

        ' The main thread exits, but the application continues to
        ' run until all foreground threads have exited.
    End Sub

    Private Sub ThreadProc()
        For i As Integer = 0 To numIterations - 1
            UseResource()
        Next
    End Sub

    ' This method represents a resource that must be synchronized
    ' so that only one thread at a time can enter.
    Private Sub UseResource()
        ' Wait until it is safe to enter.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name)
        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", 
            Thread.CurrentThread.Name)

        ' Release the Mutex.
        mut.ReleaseMutex()
        Console.WriteLine("{0} has released the mutex", 
            Thread.CurrentThread.Name)
   End Sub
End Module
' The example displays output like the following:
'       Thread1 is requesting the mutex
'       Thread2 is requesting the mutex
'       Thread1 has entered the protected area
'       Thread3 is requesting the mutex
'       Thread1 is leaving the protected area
'       Thread1 has released the mutex
'       Thread3 has entered the protected area
'       Thread3 is leaving the protected area
'       Thread3 has released the mutex
'       Thread2 has entered the protected area
'       Thread2 is leaving the protected area
'       Thread2 has released the mutex

Dans l’exemple suivant, chaque thread appelle la WaitOne(Int32) méthode pour acquérir le mutex. Si l’intervalle de délai d’attente s’écoule, la méthode retourne falseet le thread n’acquiert pas le mutex ni n’obtient l’accès à la ressource que le mutex protège. La ReleaseMutex méthode est appelée uniquement par le thread qui acquiert le mutex.

using System;
using System.Threading;

class Example
{
    // 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()
    {
        Example ex = new Example();
        ex.StartThreads();
    }

     private void StartThreads()
     {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread returns to Main and exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        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, and do not enter if the request times out.
        Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
        if (mut.WaitOne(1000)) {
           Console.WriteLine("{0} has entered the protected area", 
               Thread.CurrentThread.Name);
   
           // Place code to access non-reentrant resources here.
   
           // Simulate some work.
           Thread.Sleep(5000);
   
           Console.WriteLine("{0} is leaving the protected area", 
               Thread.CurrentThread.Name);
   
           // Release the Mutex.
              mut.ReleaseMutex();
           Console.WriteLine("{0} has released the mutex", 
                             Thread.CurrentThread.Name);
        }
        else {
           Console.WriteLine("{0} will not acquire the mutex", 
                             Thread.CurrentThread.Name);
        }
    }

    ~Example()
    {
       mut.Dispose();
    }
}
// The example displays output like the following:
//       Thread1 is requesting the mutex
//       Thread1 has entered the protected area
//       Thread2 is requesting the mutex
//       Thread3 is requesting the mutex
//       Thread2 will not acquire the mutex
//       Thread3 will not acquire the mutex
//       Thread1 is leaving the protected area
//       Thread1 has released the mutex
Imports System.Threading

Class Example
   ' Create a new Mutex. The creating thread does not own the mutex.
   Private mut As New Mutex()
   Private Const numIterations As Integer = 1
   Private Const numThreads As Integer = 3

   Public Shared Sub Main()
      Dim ex As New Example()
      ex.StartThreads()
   End Sub
   
   Private Sub StartThreads()
        ' Create the threads that will use the protected resource.
        For i As Integer = 0 To numThreads - 1
            Dim newThread As New Thread(AddressOf ThreadProc)
            newThread.Name = String.Format("Thread{0}", i + 1)
            newThread.Start()
        Next

        ' The main thread returns to Main and exits, but the application continues to
        ' run until all foreground threads have exited.
   End Sub

   Private Sub ThreadProc()
        For i As Integer = 0 To numIterations - 1
            UseResource()
        Next
   End Sub

   ' This method represents a resource that must be synchronized
   ' so that only one thread at a time can enter.
   Private Sub UseResource()
        ' Wait until it is safe to enter.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name)
        If mut.WaitOne(1000) Then
           Console.WriteLine("{0} has entered the protected area", 
               Thread.CurrentThread.Name)
   
           ' Place code to access non-reentrant resources here.
   
           ' Simulate some work.
           Thread.Sleep(5000)
   
           Console.WriteLine("{0} is leaving the protected area", 
               Thread.CurrentThread.Name)
   
           ' Release the Mutex.
           mut.ReleaseMutex()
           Console.WriteLine("{0} has released the mutex", 
                             Thread.CurrentThread.Name)
        Else
           Console.WriteLine("{0} will not acquire the mutex", 
                             Thread.CurrentThread.Name)
        End If
   End Sub
   
   Protected Overrides Sub Finalize()
      mut.Dispose()
   End Sub
End Class
' The example displays output like the following:
'       Thread1 is requesting the mutex
'       Thread1 has entered the protected area
'       Thread2 is requesting the mutex
'       Thread3 is requesting the mutex
'       Thread2 will not acquire the mutex
'       Thread3 will not acquire the mutex
'       Thread1 is leaving the protected area
'       Thread1 has released the mutex

Remarques

Lorsque plusieurs threads doivent accéder à une ressource partagée en même temps, le système a besoin d’un mécanisme de synchronisation pour s’assurer qu’un seul thread à la fois utilise la ressource. Mutex est une primitive de synchronisation qui accorde un accès exclusif à la ressource partagée à un seul thread. Si un thread acquiert un mutex, le deuxième thread qui souhaite acquérir ce mutex est suspendu jusqu’à ce que le premier thread libère le mutex.

Important

Ce type implémente l'interface IDisposable. Une fois que vous avez fini d’utiliser le type, vous devez le supprimer directement ou indirectement. Pour supprimer directement le type Dispose, appelez sa méthode dans un bloc try/catch. Pour la supprimer indirectement, utilisez une construction de langage telle que using (dans C#) ou Using (dans Visual Basic). Pour plus d’informations, consultez la section « Utilisation d’un objet qui implémente IDisposable » dans la rubrique de l’interface IDisposable.

Vous pouvez utiliser la méthode pour demander la WaitHandle.WaitOne propriété d’un mutex. Le thread appelant se bloque jusqu’à ce que l’un des éléments suivants se produise :

  • Le mutex est signalé pour indiquer qu’il n’est pas détenu. Dans ce cas, la WaitOne méthode retourne trueet le thread appelant assume la propriété du mutex et accède à la ressource protégée par le mutex. Une fois qu’il a terminé d’accéder à la ressource, le thread doit appeler la ReleaseMutex méthode pour libérer la propriété du mutex. Le premier exemple de la section Exemples illustre ce modèle.

  • L’intervalle de délai d’attente spécifié dans l’appel à une WaitOne méthode qui a un millisecondsTimeout paramètre ou timeout s’est écoulé. Dans ce cas, la WaitOne méthode retourne falseet le thread appelant ne tente plus d’acquérir la propriété du mutex. Dans ce cas, vous devez structurer votre code afin que l’accès à la ressource protégée par le mutex soit refusé au thread appelant. Étant donné que le thread n’a jamais acquis la propriété du mutex, il ne doit pas appeler la ReleaseMutex méthode. Le deuxième exemple de la section Exemples illustre ce modèle.

La Mutex classe applique l’identité de thread, de sorte qu’un mutex ne peut être libéré que par le thread qui l’a acquis. En revanche, la classe n’applique Semaphore pas l’identité de thread. Un mutex peut également être passé entre les limites du domaine d’application.

Le thread propriétaire d’un mutex peut demander le même mutex dans les appels répétés à WaitOne sans bloquer son exécution. Toutefois, le thread doit appeler la ReleaseMutex méthode le même nombre de fois pour libérer la propriété du mutex.

Étant donné que la Mutex classe hérite de WaitHandle, vous pouvez également appeler les méthodes statiques WaitHandle.WaitAll et WaitHandle.WaitAny pour synchroniser l’accès à une ressource protégée.

Si un thread se termine lors de la propriété d’un mutex, le mutex est dit abandonné. L’état du mutex est défini sur signalé, et le thread d’attente suivant obtient la propriété. À compter de la version 2.0 du .NET Framework, un AbandonedMutexException est jeté dans le thread suivant qui acquiert le mutex abandonné. Avant la version 2.0 du .NET Framework, aucune exception n’a été levée.

Attention

Un mutex abandonné indique souvent une erreur grave dans le code. Lorsqu’un thread se quitte sans libérer le mutex, les structures de données protégées par le mutex peuvent ne pas être dans un état cohérent. Le thread suivant pour demander la propriété du mutex peut gérer cette exception et continuer, si l’intégrité des structures de données peut être vérifiée.

Si le mutex est développé au niveau système, et qu’il est abandonné, cela peut indiquer qu’une application a été arrêtée soudainement (par exemple, à l’aide du Gestionnaire des tâches de Windows).

Les mutex sont de deux types : les mutex locaux, qui ne sont pas nommés, et les mutex système nommés. Un mutex local existe uniquement dans votre processus. Il peut être utilisé par n’importe quel thread de votre processus qui a une référence à l’objet Mutex qui représente le mutex. Chaque objet sans nom Mutex représente un mutex local distinct.

Les mutexes système nommés sont visibles dans tout le système d’exploitation et peuvent être utilisés pour synchroniser les activités des processus. Vous pouvez créer un Mutex objet qui représente un mutex système nommé à l’aide d’un constructeur qui accepte un nom. L’objet de système d’exploitation peut être créé en même temps, ou il peut exister avant la création de l’objet Mutex . Vous pouvez créer plusieurs objets Mutex qui représentent le même mutex de système nommé, et vous pouvez utiliser la méthode OpenExisting pour ouvrir un mutex de système nommé existant.

Notes

Sur un serveur qui exécute Terminal Services, un mutex système nommé peut avoir deux niveaux de visibilité. Si son nom commence par le préfixe Global\, le mutex est visible dans toutes les sessions terminal server. Si son nom commence par le préfixe Local\, le mutex est visible uniquement dans la session terminal server où il a été créé. Dans ce cas, un mutex distinct portant le même nom peut exister dans chacune des autres sessions terminal server sur le serveur. Si vous ne spécifiez pas de préfixe lorsque vous créez un mutex nommé, il prend le préfixe Local\. Dans une session terminal server, deux mutex dont les noms diffèrent uniquement par leurs préfixes sont des mutex distincts, qui sont tous deux visibles par tous les processus de la session Terminal Server. Autrement dit, les noms Global\ de préfixe et Local\ décrivent l’étendue du nom mutex par rapport aux sessions terminal server, et non par rapport aux processus.

Attention

Par défaut, un mutex nommé n’est pas limité à l’utilisateur qui l’a créé. D’autres utilisateurs peuvent être en mesure d’ouvrir et d’utiliser le mutex, notamment en interférant avec le mutex en entrant le mutex sans le quitter. Sur les systèmes d’exploitation de type Unix, le système de fichiers est utilisé dans l’implémentation de mutex nommés, et d’autres utilisateurs peuvent être en mesure d’interférer avec les mutex nommés de manière plus significative. Sur Windows, pour restreindre l’accès à des utilisateurs spécifiques, vous pouvez utiliser une surcharge de constructeur ou MutexAcl et passer un MutexSecurity lors de la création du mutex nommé. Sur les systèmes d’exploitation de type Unix, il n’existe actuellement aucun moyen de restreindre l’accès à un mutex nommé. Évitez d’utiliser des mutex nommés sans restrictions d’accès sur les systèmes qui peuvent avoir des utilisateurs non approuvés exécutant du code.

La barre oblique inverse (\) est un caractère réservé dans un nom mutex. N’utilisez pas de barre oblique inverse (\) dans un nom mutex, sauf comme spécifié dans la note sur l’utilisation des mutex dans les sessions terminal server. Sinon, une DirectoryNotFoundException peut être levée, même si le nom du mutex représente un fichier existant.

Constructeurs

Mutex()

Initialise une nouvelle instance de la classe Mutex avec des propriétés par défaut.

Mutex(Boolean)

Initialise une nouvelle instance de la classe Mutex avec une valeur booléenne qui indique si le thread appelant doit avoir la propriété initiale du mutex.

Mutex(Boolean, String)

Initialise une nouvelle instance de la classe Mutex avec une valeur booléenne qui indique si le thread appelant doit avoir la propriété initiale du mutex, et une chaîne représentant le nom du mutex.

Mutex(Boolean, String, Boolean)

Initialise une nouvelle instance de la classe Mutex avec une valeur booléenne qui indique si le thread appelant doit avoir la propriété initiale du mutex, une chaîne qui représente le nom du mutex et une valeur booléenne qui, quand la méthode retourne son résultat, indique si la propriété initiale du mutex a été accordée au thread appelant.

Mutex(Boolean, String, Boolean, MutexSecurity)

Initialise une nouvelle instance de la classe Mutex avec une valeur booléenne qui indique si le thread appelant doit avoir la propriété initiale du mutex, une chaîne qui représente le nom du mutex et une variable booléenne qui, quand la méthode retourne son résultat, indique si la propriété initiale du mutex a été accordée au thread appelant, ainsi que la sécurité de contrôle d'accès à appliquer au mutex nommé.

Champs

WaitTimeout

Indique que le délai fixé pour une opération WaitAny(WaitHandle[], Int32, Boolean) a été dépassé sans qu'aucun des handles d'attente n'ait été signalé. Ce champ est constant.

(Hérité de WaitHandle)

Propriétés

Handle
Obsolète.
Obsolète.

Obtient ou définit le handle du système d'exploitation natif.

(Hérité de WaitHandle)
SafeWaitHandle

Obtient ou définit le handle du système d'exploitation natif.

(Hérité de WaitHandle)

Méthodes

Close()

Libère toutes les ressources détenues par le WaitHandle actuel.

(Hérité de WaitHandle)
CreateObjRef(Type)

Crée un objet contenant toutes les informations appropriées requises pour générer un proxy permettant de communiquer avec un objet distant.

(Hérité de MarshalByRefObject)
Dispose()

Libère toutes les ressources utilisées par l'instance actuelle de la classe WaitHandle.

(Hérité de WaitHandle)
Dispose(Boolean)

En cas de substitution dans une classe dérivée, libère les ressources non managées utilisées par WaitHandle et libère éventuellement les ressources managées.

(Hérité de WaitHandle)
Equals(Object)

Détermine si l'objet spécifié est égal à l'objet actuel.

(Hérité de Object)
GetAccessControl()

Obtient un objet MutexSecurity qui représente la sécurité de contrôle d'accès pour le mutex nommé.

GetHashCode()

Fait office de fonction de hachage par défaut.

(Hérité de Object)
GetLifetimeService()
Obsolète.

Récupère l'objet de service de durée de vie en cours qui contrôle la stratégie de durée de vie de cette instance.

(Hérité de MarshalByRefObject)
GetType()

Obtient le Type de l'instance actuelle.

(Hérité de Object)
InitializeLifetimeService()
Obsolète.

Obtient un objet de service de durée de vie pour contrôler la stratégie de durée de vie de cette instance.

(Hérité de MarshalByRefObject)
MemberwiseClone()

Crée une copie superficielle du Object actuel.

(Hérité de Object)
MemberwiseClone(Boolean)

Crée une copie superficielle de l'objet MarshalByRefObject actuel.

(Hérité de MarshalByRefObject)
OpenExisting(String)

Ouvre le mutex nommé spécifié, s'il existe déjà.

OpenExisting(String, MutexRights)

Ouvre le mutex nommé spécifié, s'il existe déjà, avec l'accès de sécurité souhaité.

ReleaseMutex()

Libère l'objet Mutex une seule fois.

SetAccessControl(MutexSecurity)

Définit la sécurité de contrôle d'accès pour un mutex système nommé.

ToString()

Retourne une chaîne qui représente l'objet actuel.

(Hérité de Object)
TryOpenExisting(String, Mutex)

Ouvre le mutex nommé spécifié, s'il existe déjà, et retourne une valeur indiquant si l'opération a réussi.

TryOpenExisting(String, MutexRights, Mutex)

Ouvre le mutex nommé spécifié, s'il existe déjà, avec l'accès de sécurité souhaité, puis retourne une valeur indiquant si l'opération a réussi.

WaitOne()

Bloque le thread actuel jusqu'à ce que le WaitHandle actuel reçoive un signal.

(Hérité de WaitHandle)
WaitOne(Int32)

Bloque le thread actuel jusqu'à ce que le WaitHandle actuel reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l'intervalle de temps.

(Hérité de WaitHandle)
WaitOne(Int32, Boolean)

Bloque le thread actuel jusqu’à ce que le WaitHandle actuel reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

(Hérité de WaitHandle)
WaitOne(TimeSpan)

Bloque le thread actuel jusqu'à ce que l'instance actuelle reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps.

(Hérité de WaitHandle)
WaitOne(TimeSpan, Boolean)

Bloque le thread actuel jusqu'à ce que l'instance actuelle reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps et en spécifiant s'il faut quitter le domaine de synchronisation avant l'attente.

(Hérité de WaitHandle)

Implémentations d’interfaces explicites

IDisposable.Dispose()

Cette API prend en charge l'infrastructure du produit et n'est pas destinée à être utilisée directement à partir de votre code.

Libère toutes les ressources utilisées par WaitHandle.

(Hérité de WaitHandle)

Méthodes d’extension

GetAccessControl(Mutex)

Retourne les descripteurs de sécurité pour le mutex spécifié.

SetAccessControl(Mutex, MutexSecurity)

Définit les descripteurs de sécurité pour le mutex spécifié.

GetSafeWaitHandle(WaitHandle)

Obtient le handle sécurisé pour un handle d’attente de système d’exploitation natif.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Définit un handle sécurisé pour un handle d’attente de système d’exploitation natif.

S’applique à

Cohérence de thread

Ce type est thread-safe.

Voir aussi