web-dev-qa-db-fra.com

Les méthodes statiques sont-elles sécuritaires pour les threads

J'ai une classe de minuteur statique qui sera appelée par N'IMPORTE QUELLE page Web pour calculer combien de temps chaque page a pris pour être construite.

Ma question est: les classes statiques sont-elles protégées contre les threads? Dans mon exemple, les utilisateurs simultanés causeront-ils un problème avec mes heures de début et de fin? par exemple, un thread différent écrasant mes valeurs de début et de fin.

public static class Timer
{
    private static DateTime _startTime;
    private static DateTime _stopTime;    

    /// <summary>
    /// Gets the amount of time taken in milliseconds
    /// </summary>
    /// <returns></returns>
    public static decimal Duration()
    {
        TimeSpan duration =  _stopTime - _startTime;
        return duration.Milliseconds;
    }

    public static void Start()
    {
        _startTime = DateTime.Now;
    }

    public static void Stop()
    {
        _stopTime = DateTime.Now;
    }
}

Cette classe doit-elle être une classe non statique?

(Cette classe sera appelée depuis la page principale asp.net.)

56
Th3Fix3r

Les méthodes statiques ne sont pas intrinsèquement thread-safe. Ils ne sont pas traités différemment par le CLR que les méthodes d'instance. La différence est que l'on devrait généralement essayer de rendre les thread-safe. (Je ne peux penser à aucune méthode statique .NET BCL qui ne soit pas thread-safe.) Les méthodes d'instance ne sont souvent pas thread-safe car le modèle typique est de créer un objet et de l'utiliser à plusieurs reprises à partir d'un thread, et s'il le fait doit être utilisé à partir de plusieurs threads, la coordination implique de s'assurer que l'objet est utilisé en toute sécurité. Dans de très nombreux cas, c'est plus approprié de le faire dans le code de coordination que dans l'objet lui-même. (Habituellement, vous voulez rendre atomiques des séquences entières d'opérations - quelque chose qui ne peut pas être fait dans l'objet.)

Votre classe Timer n'est certainement pas sécurisée pour les threads: deux threads peuvent facilement taper sur les données de l'autre, et rien n'empêche un thread d'utiliser des données "périmées" lors du calcul de la durée.

Utilisez la classe Stopwatch à la place - c'est pour cela que c'est là. Certes, si vous souhaitez utiliser une instance à partir de plusieurs threads, vous devrez prendre les mesures normales pour assurer la sécurité, mais vous serez en bien meilleure position en général. Certes, Stopwatch est loin d'être parfait aussi - voir cette question et le commentaire ci-dessous pour plus de détails - mais c'est au moins pour cela que le type est conçu. (Qui sait, ça peut être réparé quelque temps ...)

65
Jon Skeet

Il y a une bonne discussion ici qui se concentre davantage sur les mécanismes et les raisons pour lesquelles votre exemple n'est pas thread-safe.

Pour résumer, tout d'abord, vos variables statiques seront partagées. Si vous pouviez en faire des variables locales, même si elles sont locales à une méthode statique, elles obtiendraient toujours leur propre cadre de pile et seraient donc thread-safe. En outre, si vous protégez autrement vos variables statiques (c'est-à-dire les verrous et/ou d'autres techniques de programmation multi-thread mentionnées par d'autres dans ce thread), vous pouvez également rendre votre exemple de classe statique thread-safe.

Deuxièmement, parce que votre exemple ne prend pas en compte les instances de variables externes que vous modifiez ou dont l'état pourrait être modifié par un autre thread, votre exemple est également thread-safe à cet égard.

23
Bill

Votre classe de minuteur n'est certainement pas thread-safe. Vous devez créer une classe normale et l'instancier à chaque fois que vous devez mesurer le temps:

Timer timer = new Timer();

timer.Start();
//...
timer.Stop();

decimal duration = timer.Duration();

Mieux encore, il existe une classe .NET intégrée qui fait exactement cela:

Stopwatch sw = Stopwatch.StartNew();

sw.Stop();

TimeSpan duration = sw.Elapsed;
20
Philippe Leybaert

Oui, vous avez raison, les membres/accesseurs statiques de cette classe les feront écraser par différents utilisateurs.

C'est pourquoi vous avez des instances et des membres non statiques.

5
Tom