Летучий против Блокированный против блокировки

            //For me it's the best way to look for the value of a spezific column
            int seekValue = 5;
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                var columnValue = Convert.ToInt32(row.Cells["ColumnName"].Value);
                if (columnValue == seekValue)
                {
                    dataGridView1.CurrentCell = row.Cells[0];
                }
            }
636
задан Sam 22 August 2014 в 14:31
поделиться

6 ответов

Худший (не будет на самом деле работать)

Изменение, которое упомянул модификатор доступа counter к public volatile

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

, Если это не volatile, и ЦП инкременты значение, затем ЦП B не может на самом деле видеть, что увеличенное значение до некоторое время спустя, который может вызвать проблемы.

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

Почти лучше всего:

lock(this.locker) this.counter++;

Это безопасно сделать (если Вы еще помните к lock везде, что Вы получаете доступ this.counter). Это препятствует тому, чтобы любые другие потоки выполнили любой другой код, который охраняют locker. Используя блокировки также, предотвращает проблемы переупорядочения мульти-ЦП как выше, который является большим.

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

Лучший

Interlocked.Increment(ref this.counter);

Это безопасно, поскольку это эффективно делает чтение, инкремент, и пишет в 'одном хите', который не может быть прерван. Из-за этого это не будет влиять ни на какой другой код, и Вы не должны помнить блокировать в другом месте также. Это также очень быстро (как MSDN заявляет на современных центральных процессорах, это - часто буквально единственная инструкция по ЦП).

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

InterlockedNotes:

  1. ВЗАИМНО БЛОКИРУЕМЫЕ МЕТОДЫ ОДНОВРЕМЕННО БЕЗОПАСНЫ НА ЛЮБОМ КОЛИЧЕСТВЕ ЯДЕР ИЛИ ЦЕНТРАЛЬНЫХ ПРОЦЕССОРОВ.
  2. Взаимно блокируемые методы применяют весь забор вокруг инструкций, которые они выполняют, таким образом переупорядочивания не происходит.
  3. Взаимно блокируемые методы не нужны или даже делают не доступ к поддержке к энергозависимому полю , когда энергозависимый помещается, половина ограждает операции на данном поле и взаимно блокировалась, использует весь забор.

Сноска: Для чего энергозависимый на самом деле хорошо.

Как [1 111] не предотвращает эти виды проблем многопоточности, для чего это? Хороший пример говорит, что у Вас есть два потока, тот, который всегда пишет в переменную (говорят queueLength), и тот, который всегда читает из той же самой переменной.

, Если queueLength не энергозависимо, поток A может записать пять раз, но распараллелить B, может видеть те записи, как откладываемые (или даже потенциально в неправильном порядке).

решение для А состояло бы в том, чтобы заблокировать, но Вы могли также использовать энергозависимый в этой ситуации. Это гарантировало бы, что поток B будет всегда видеть самую актуальную вещь, которые распараллеливают A, записал. Обратите внимание однако, что эта логика [только 1 117] работы, если у Вас есть писатели, которые никогда не читали, и читатели, которые никогда не пишут, и , если вещь Вы пишете, являются атомарным значением. Как только Вы делаете единственный read-modify-write, необходимо перейти к Взаимно блокируемым операциям или использовать Блокировку.

821
ответ дан Keyur Ramoliya 22 August 2014 в 14:31
поделиться

РЕДАКТИРОВАНИЕ: , Как отмечено в комментариях, в эти дни я рад использовать Interlocked для случаев единственная переменная , где это , очевидно хорошо. Когда это станет более сложным, я все еще вернусь к блокировке...

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

Лично я почти всегда просто блокирую - легче разобраться способом, который является , очевидно прямо или, чем энергозависимость или, чем Взаимно блокируется. Инкремент. Насколько я заинтересован, многопоточность без блокировок настоящая экспертов по поточной обработке, из которых я не тот. Если Joe Duffy и его команда создают хорошие библиотеки, которые параллелизируют вещи без такой же блокировки как что-то, что я создал бы, это невероятно, и я буду использовать его в heartbeat - но когда я сделаю поточную обработку меня, я пытаюсь сохранить его простым.

135
ответ дан Yair Nevet 22 August 2014 в 14:31
поделиться

" volatile" не заменяет Interlocked.Increment! Это просто удостоверяется, что переменная не кэшируется, но используется непосредственно.

Постепенное увеличение переменной требует на самом деле трех операций:

  1. читает
  2. инкремент
  3. , запись

Interlocked.Increment выполняет все три части как единственную атомарную операцию.

42
ответ дан Michael Damatov 22 August 2014 в 14:31
поделиться

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

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

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

Это - действительно хорошая статья, если Вы хотите читать больше о коде без блокировок и правильном способе приблизиться к записи ее

http://www.ddj.com/hpc-high-performance-computing/210604448

15
ответ дан Lou Franco 22 August 2014 в 14:31
поделиться

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

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

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

11
ответ дан Rob Walker 22 August 2014 в 14:31
поделиться

Я провел несколько тестов, чтобы увидеть, как на самом деле работает теория: kennethxu.blogspot.com/2009/05/interlocked-vs-monitor-performance.html . Мой тест был больше ориентирован на CompareExchnage, но результат для Increment был аналогичным. Взаимоблокировка не требуется быстрее в среде с несколькими процессорами. Вот результат теста для Increment на сервере с 16 процессорами, которому 2 года. Помните, что тест также включает в себя безопасное чтение после увеличения, что типично в реальном мире.

D:\>InterlockVsMonitor.exe 16
Using 16 threads:
          InterlockAtomic.RunIncrement         (ns):   8355 Average,   8302 Minimal,   8409 Maxmial
    MonitorVolatileAtomic.RunIncrement         (ns):   7077 Average,   6843 Minimal,   7243 Maxmial

D:\>InterlockVsMonitor.exe 4
Using 4 threads:
          InterlockAtomic.RunIncrement         (ns):   4319 Average,   4319 Minimal,   4321 Maxmial
    MonitorVolatileAtomic.RunIncrement         (ns):    933 Average,    802 Minimal,   1018 Maxmial
7
ответ дан 22 November 2019 в 21:49
поделиться
Другие вопросы по тегам:

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