В C# был бы это быть лучше использовать Очередь. Синхронизируемый или блокировка () для потокобезопасности?

Приведенный ниже пример, похоже, работал. Просто устанавливая высоту для первого элемента

<ul class="row">
    <li class="span4" style="height: 100px"><h1>1</h1></li>
    <li class="span4"><h1>2</h1></li>
    <li class="span4"><h1>3</h1></li>
    <li class="span4"><h1>4</h1></li>
    <li class="span4"><h1>5</h1></li>
    <li class="span4"><h1>6</h1></li>
    <li class="span4"><h1>7</h1></li>
    <li class="span4"><h1>8</h1></li>
</ul>

Я не могу не думать, что это неправильное использование строки.

58
задан Jon Tackabury 3 December 2008 в 21:13
поделиться

5 ответов

Лично я всегда предпочитаю блокировать. Это означает, что Вы добираетесь для решения гранулярности. Если Вы просто полагаетесь на Синхронизируемую обертку, каждая отдельная операция синхронизируется, но если когда-нибудь необходимо делать больше чем одну вещь (например, выполняющий итерации по целому набору) необходимо заблокировать так или иначе. В интересах простоты я предпочитаю просто иметь одну вещь помнить - блокировка соответственно!

РЕДАКТИРОВАНИЕ: Как отмечено в комментариях, если Вы можете использование абстракции более высокого уровня, это является большим. И если Вы делаете блокировка использования, будьте осторожны с нею - документ, что Вы ожидаете быть заблокированными, где, и получают/выпускают блокировки в течение максимально короткого периода (больше для правильности, чем производительность). Постарайтесь не звонить в неизвестный код при содержании блокировки, избегайте вложенных блокировок и т.д.

В.NET 4 существует партия [еще 113] поддержка высокоуровневых абстракций (включая код без блокировок). Так или иначе я все еще не рекомендовал бы использовать синхронизируемые обертки.

47
ответ дан Jon Skeet 7 November 2019 в 15:27
поделиться

Существует основная проблема с эти Synchronized методы в старой библиотеке набора, в этом они синхронизируются на слишком низком уровне гранулярности (на метод, а не на единицу работы).

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

object item;
if (queue.Count > 0)
{
    // at this point another thread dequeues the last item, and then
    // the next line will throw an InvalidOperationException...
    item = queue.Dequeue();
}

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

object item;
lock (queue)
{
    if (queue.Count > 0)
    {
        item = queue.Dequeue();
    }
}

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

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

35
ответ дан Greg Beech 7 November 2019 в 15:27
поделиться

Часто существует сила между требованиями 'ориентированных на многопотоковое исполнение наборов' и требования для выполнения нескольких операций на наборе атомарным способом.

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

, А также перечисление, общие операции как "уже являются этим объектом в очереди? Нет, тогда я добавлю, что это" также требует синхронизации, которая более широка, чем просто очередь.

15
ответ дан Will Dean 7 November 2019 в 15:27
поделиться

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

object item;
if (queue.Count > 0)
{
  lock (queue)
  {
    if (queue.Count > 0)
    {
       item = queue.Dequeue();
    }
  }
}
7
ответ дан Leonidius 7 November 2019 в 15:27
поделиться

Мне что использование блокировки (...) кажется ясным {...} Блокировка является правильным ответом.

Для гарантии потокобезопасности Очереди все операции должны быть сделаны через эту обертку только.

, Если другие потоки получат доступ к очереди, не используя.Synchronized (), то Вы будете ручьем - если весь Ваш доступ очереди не будет заперт.

1
ответ дан Greg Hurlman 7 November 2019 в 15:27
поделиться
Другие вопросы по тегам:

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