2011-10-12 2 views
1

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

Что произойдет, когда это произойдет?

Чтобы обеспечить некоторый контекст, класс используется для выполнения запроса linq-to-sql: он получает несколько параметров, включая UserID, и возвращает список пользовательских объектов.

спасибо.

+3

непреодолимых упоры силы и недвижимое движение объекта – BrokenGlass

ответ

3

Что произойдет, когда это произойдет?

Если ваши методы reentrant, тогда они являются потокобезопасными, и что произойдет, так это то, что, скорее всего, они будут работать. Если эти статические методы полагаются на какое-то общее состояние, и вы не синхронизировали доступ к этому состоянию, возможно, это разделенное состояние будет повреждено. Но вам не нужно ударять метод на той же наносекунде на 20 запросов на повреждение вашего общего состояния. 2 достаточно, если вы не синхронизируете его.

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


UPDATE:

Потому что в комментариях вы упомянули LINQ-TO-SQL, если все переменные, используемые в статическом методе являются локальными, этот метод является потокобезопасным. Например:

public static SomeEntity GetEntity(int id) 
{ 
    using (var db = new SomeDbContext()) 
    { 
     return db.SomeEntities.FirstOrDefault(x => x.Id == id); 
    } 
} 
+0

Статический класс используется для запроса linq-to-sql. Плохая идея? – frenchie

+0

@frenchie, если этот статический класс не полагается на статические ресурсы, которые не являются потокобезопасными, вы должны быть в порядке. –

+0

@frenchie, я обновил свой ответ, чтобы предоставить пример потокобезопасного метода, который можно использовать с Linq-To-SQL. –

0

Он врезается в неприятную образом (если вы делаете это, чтобы разделить состояние), не делать это в веб-приложение ... Или Alternativly защитить чтение/запись с замком:

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

Но, честно говоря, вам действительно следует избегать использования статики, если только вы НЕ ДОЛЖНЫ это сделать, и если вам действительно нужно быть очень осторожным с вашей стратегией блокировки и проверить ее на уничтожение, чтобы убедиться, что удалось изолировать чтение и запись друг от друга

+0

Кто сказал, что ничего об читает и пишет? Нет никаких доказательств того, что это использует * любое * общее состояние. –

+0

@Jon: Успение - это опасная вещь, я предположил, что OP делал это, чтобы разделить состояние между потоками. Я обновил свой пост, чтобы отразить это, так же, как вы разместили свой комментарий. – JonAlb

2

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

+0

Что такое поточно-безопасное? – frenchie

+0

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

5

Это полностью зависит от того, что означает ваша «определенная работа». Если это не касается какого-либо общего состояния, это абсолютно нормально. Если для этого требуется доступ к общему состоянию, вам нужно будет решить, как справиться с этим поточно-безопасным способом.

Общее правило: общедоступный API класса должен быть потокобезопасным для статических методов, но не должен быть поточно-безопасным, например, методы - обычно любой экземпляр используется только в одном нить. Конечно, это зависит от того, что делает ваш класс, и what you mean by thread-safe.

+0

Я использую класс для запроса linq-to-sql; это плохая идея? Должен ли класс не быть статическим и быть создан для каждого использования? – frenchie

+0

@frenchie: Это довольно неопределенный термин - прочитайте связанное сообщение в блоге. Но в ручных волнообразных выражениях это означает, что «плохие вещи не произойдут, если несколько потоков одновременно вызовут один и тот же код» в определенном контексте. –

+1

@frenchie: сам DataContext Linq2SQL не является потокобезопасным. Пока каждый вспомогательный вызов инициализирует свой собственный контекст и вы не получаете доступа к каким-либо другим статически общим ресурсам, вы должны быть в порядке –

1

Это зависит от того, имеет ли статический класс какое-либо состояние или нет (т. Е. Статические переменные, разделяемые всеми вызовами). Если это не так, тогда все в порядке. Если это так, это не хорошо. Примеры:

// Fine 
static class Whatever 
{ 
    public string DoSomething() { 
     return "something"; 
    } 
} 

// Death from above 
static class WhateverUnsafe 
{ 
    static int count = 0; 
    public int Count() { 
     return ++count; 
    } 
} 

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

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

+0

Ok; Я использую статический класс для запроса linq-to-sql. Если я это сделаю? Я думал, что, но сохраните класс static, я сохраняю стоимость создания объекта. – frenchie

+0

Я сомневаюсь, что вам придется беспокоиться о стоимости объекта. Это не дорого, плюс я не уверен, что Linq2Sql является потокобезопасным. – Deleted

Смежные вопросы