Сохраняются ли синглтоны автоматически между запросами в ASP.NET MVC? - PullRequest
3 голосов
/ 12 августа 2010

У меня есть справочная таблица (LUT) из тысяч целых чисел, которую я использую при достаточном количестве запросов для вычисления содержимого на основе того, что было извлечено из базы данных.

Если я просто создаю стандартный синглтон для хранения LUT, автоматически ли он сохраняется между запросами или мне специально нужно перевести его в состояние приложения?

Если они автоматически сохраняются, то в чем разница, сохраняя их с состоянием приложения?

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

РЕДАКТИРОВАТЬ: 4-я версия Джона Скита выглядит многообещающе http://csharpindepth.com/Articles/General/Singleton.aspx

public sealed class Singleton
{
    static readonly Singleton instance=new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }

    // randomguy's specific stuff. Does this look good to you?
    private int[] lut = new int[5000];

    public int Compute(Product p) {
        return lut[p.Goo];
    }
}

Ответы [ 3 ]

2 голосов
/ 12 августа 2010

Да, статические члены сохраняются (это не то же самое, что постоянные - они не "сохраняются", они никогда не исчезают), что включает реализации синглтона.Вы получаете степень ленивой инициализации бесплатно, как если бы она была создана в статическом присваивании или статическом конструкторе, она не будет вызываться до тех пор, пока соответствующий класс не будет впервые использован.Это создание блокируется по умолчанию, но все другие варианты использования, как вы говорите, должны быть поточно-ориентированными.Принимая во внимание степень параллелизма, тогда, если синглтон не будет неизменным (ваша справочная таблица не изменяется в течение времени жизни приложения), вы должны быть очень осторожны с тем, как его обновлять (один из способов - поддельный синглтон).- при обновлении вы создаете новый объект, а затем фиксируете его, присваивая ему замену текущего значения; не строго одноэлементный, хотя он выглядит как «извне»).состояние подозрительно, особенно когда речь идет о протоколе без сохранения состояния, таком как сеть.Тем не менее, он может быть хорошо использован, особенно как кэш-память постоянных или почти постоянных данных в памяти, особенно если он включает в себя граф объектов, который не может быть легко получен из базы данных.

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

Правка, чтобы соответствовать правке в вопросе:

Моя большая проблема - как инициализируется массив.Ясно, что этот пример неполон, так как он будет иметь только 0 для каждого элемента.Если он устанавливается при инициализации и доступен только для чтения, тогда все в порядке.Если он изменчив, то будьте очень, очень осторожны с вашими потоками.

Также помните о негативном влиянии слишком большого количества таких поисков на масштабирование.Несмотря на то, что вы сохраняете для большинства запросов предварительный расчет, при обновлении синглтона получается период очень тяжелой работы.Долгосрочный запуск, вероятно, будет терпимым (так как это будет не очень часто), но произвольные замедления, происходящие впоследствии, могут быть сложно проследить до их источника.

2 голосов
/ 12 августа 2010

Я бы не стал полагаться на статичность, существующую между запросами. [Всегда есть, хотя и маловероятно, вероятность того, что процесс будет сброшен между запросами.] Я бы порекомендовал объект Cache HttpContext для сохранения общих ресурсов между запросами.

0 голосов
/ 12 августа 2010

Редактировать: см. Комментарии Джона о блокировке только для чтения.

Прошло много времени с тех пор, как я имел дело с синглтоном (я предпочитаю, чтобы мой контейнер IOC имел дело с временами жизни), но вот как вы можете справиться свопросы безопасности потоков.Вам нужно заблокировать все, что изменяет состояние синглтона.Операции только для чтения, например, для Compute(int) блокировка не требуется.

// I typically create one lock per collection, but you really need one per set of atomic operations; if you ever modify two collections together, use one lock.
private object lutLock = new object();
private int[] lut = new int[5000];

public int Compute(Product p) {
    return lut[p.Goo];
}

public void SetValue(int index, int value)
{
    //lock as little code as possible. since this step is read only we don't lock it.
    if(index < 0 || index > lut.Length)
    {
        throw new ArgumentException("Index not in range", "index");
    }
    // going to mutate state so we need a lock now
    lock(lutLock)
    {
        lut[index] = value;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...