Вопрос по asp.net, c# – Статические методы являются потокобезопасными

54

У меня есть статический класс таймера, который будет вызываться ЛЮБОЙ веб-страницей, чтобы вычислить, сколько времени понадобилось для создания каждой страницы.

Мой вопрос, являются ли статические классы потокобезопасными? В моем примере будут ли параллельные пользователи вызывать проблемы с моим временем запуска и остановки? например, другие потоки перезаписывают мои начальные и конечные значения.

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;
    }
}

Должен ли этот класс быть нестатическим?

(Этот класс будет вызываться с главной страницы asp.net.)

MSDN: «Несмотря на то, что экземпляр класса содержит отдельную копию всех полей экземпляра класса, существует только одна копия каждого статического поля». colithium

Ваш Ответ

4   ответа
4

вы правы, статические члены / средства доступа в этом классе будут вызывать их перезапись разными пользователями.

Вот почему у вас есть экземпляры и нестатические члены.

64

inherently потокобезопасный. Они обрабатываются CLR не иначе, как методы экземпляра. Разница в том, что обычно нужно старатьсяmake они потокобезопасны. (Я не могу думать о каких-либо статических методах .NET BCL, которые не являются поточно-ориентированными.) Методы экземпляра часто не являются поточно-ориентированными, поскольку типичным шаблоном является создание объекта и многократное использование его из одного потока, и если онdoes должны быть использованы из нескольких потоков, координация включает в себя обеспечение безопасного использования объекта. В очень многих случаях это более целесообразно делать в координирующем коде, чем в самом объекте. (Обычно вы хотите сделать целые последовательности операций эффективно атомарными - то, что нельзя сделать внутри объекта.)

ВашTimer класс, безусловно, не является поточно-ориентированным: два потока могут с легкостью помешать друг другу данным, и ничто не мешает потоку использовать "устаревшие" Данные при расчете длительности.

ИспользоватьStopwatch класс вместо этого - это то, для чего он существует. Конечно, если вы хотите использовать один экземпляр из нескольких потоков, вам нужно будет предпринять обычные шаги для обеспечения безопасности, но в целом вы будете в гораздо лучшем положении. по общему признаниюStopwatch тоже далек от совершенстваэтот вопрос и комментарий ниже для более подробной информации - но это как минимум то, для чего предназначен тип. (Кто знает, это может быть исправлено некоторое время ...)

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/a/7919483/216440
22

Вот это больше фокусируется на механизмах и причинах того, почему ваш пример не является потокобезопасным.

Подводя итог, во-первых, ваши статические переменные будут разделены. Если бы вы могли сделать их локальными переменными, даже если они являются локальными для статического метода, они все равно получили бы свой собственный кадр стека и, таким образом, были бы поточно-ориентированными. Кроме того, если вы иначе защитите свои статические переменные (например, блокировки и / или другие методы многопоточного программирования, упомянутые другими в этой теме), вы также можете сделать ваш пример статического класса поточно-ориентированным.

Во-вторых, поскольку ваш пример не принимает экземпляры внешних переменных, которые вы изменяете или на состояние которых может воздействовать другой поток, ваш пример также является поточно-ориентированным в этом отношении.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
19

рмальный класс и создавать его каждый раз, когда вам нужно измерить время:

Timer timer = new Timer();

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

decimal duration = timer.Duration();

Более того, есть встроенный класс .NET, который делает именно это:

Stopwatch sw = Stopwatch.StartNew();

sw.Stop();

TimeSpan duration = sw.Elapsed;

Похожие вопросы