Рассмотрение безопасности потока для статического свойства как экземпляра этого класса - PullRequest
0 голосов
/ 18 декабря 2018

Пожалуйста, рассмотрите этот код:

public class BusinessClass
{
    static BusinessClass myClass { get; set; }
    Repository repo;

    public BusinessClass()
    {
        if (repo == null)
            repo = new RepositoryClass();
    }

    public static BusinessClass Instance
    {
        get
        {
            if (myClass == null)
                myClass = new BusinessClass();
            return myClass ;
        }
    }

    public void Update(Entity Item)
    {
        repo.Update(Item);
    }
}

, и я хочу использовать это BL на моей веб-странице, например:

BusinessClass.Instance.Update(Item);

Мой вопрос: является ли этот код проблематичнымдля безопасности потока?Могут ли два человека собраться одновременно в методе Update?

Спасибо

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Первый случай - блокировка сеанса asp.net

Если вы используете формы asp.net и сеанс asp.net, тогда сеанс блокирует весь вызов для всех пользователей, не нужно дополнительно заботиться о синхронизации .

Относительные вопросы:

Предотвращает ли веб-формы ASP.NET отправку с двойным щелчком мыши?
Попытка сделать веб-метод асинхронным
Веб-приложение заблокировано при обработке другого веб-приложения при совместном использовании одного сеанса
Какие счетчики perfmon полезны для выявления узких мест ASP.NET?
Полная замена сеанса ASP.Net

Второй случай - локальный поток.

Если вы не используете сеанс asp.net, или если вы открываете дополнительные потоки по одному и тому же вызову , то вам необходимо заблокировать манипуляции со статическими данными.

public class BusinessClass
{
    private static readonly object oLock = new object();

    static BusinessClass myClass { get; set; } = null;
    Repository repo;

    public BusinessClass()
    {
        if (repo == null)
            repo = new RepositoryClass();
    }

    public static BusinessClass Instance
    {
        get
        {
            if myClass == null)
            {
                lock (oLock)
                {
                    if myClass == null)
                        myClass = new BusinessClass();
                }
            }
            return myClass  
        }
    }

    public void Update(Entity Item)
    {
        repo.Update(Item);
    }
}

Окончательный вариант - глобальное изменение

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

Тогда вам нужно мьютекс для синхронизации всех вызовов.

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

Еще нужно учесть - многопользовательская среда.

Подумайте над этим сценарием.
Пользователь A и B загружают одну и ту же страницу, одну и ту жеданные, и каждый из них меняет их.

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

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

0 голосов
/ 18 декабря 2018

Это не поточно-ориентированный.Вот только один пример того, что может произойти:

Thread1: if (myClass == null) <- получает истину, потому что это нуль </p>

Thread1: [temp1] = new BusinessClass(); <- <code>[temp1] существует неявнов потоке 1

поток 2: if (myClass == null) <- получает истину, поскольку он все еще равен нулю </p>

поток 2: [temp2] = new BusinessClass(); <- <code>[temp2] существует неявно в потоке 2

Thread2: myClass = [temp2];

Thread2: return myClass; <- возвращает созданный второй экземпляр </p>

Thread1: myClass = [temp1];

Thread1: return myClass; <- возвращает первыйэкземпляр создан </p>

Теперь каждый поток содержит отдельный экземпляр "singleton" Instance.


Простая в использовании поточная безопасная прямая альтернатива будетиспользуйте Lazy<BusinessClass> для хранения вашего экземпляра-одиночки вместо myClass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...