Параллельность и синхронизация - PullRequest
3 голосов
/ 10 октября 2010

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

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

Возьмите следующий код:

int i = 0;

if( blockingCondition )
{
  lock( objLock )
  {
    i++;
  }
}

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

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

Кроме того, .net TPL обрабатывает этот тип синхронизации? А как насчет других языков?

EDIT Обратите внимание, что это не о потоках, а Tasks и Parallel-Processisng.

РЕДАКТИРОВАТЬ 2 ОК, спасибо за информацию всем. Так правда ли, что ОС обеспечит сериализацию записи в память, обеспечивая многоядерную синхронизацию через энергозависимые операции чтения?

Ответы [ 3 ]

2 голосов
/ 10 октября 2010

Чтобы понять, почему это работает, имейте в виду:

  1. Блокировка блокировки (то есть увеличение семафор блокировки на объекте) операция, которая блокирует, если объект уже заблокирован.

  2. Два шага lock, а) проверка блокировки Семафор свободен, б) и на самом деле блокировка объекта, выполняются «одновременно» - то есть они монолитная или атомная операция как насколько отношения между процессором и память обеспокоена.

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

1 голос
/ 10 октября 2010

Блокировка, как вы описали здесь, представляет собой блокировку в стиле " Monitor " на objLock. Как вы заметили, в многоядерной системе вполне возможно, чтобы два «блокировочных» вызова одновременно начинались с . Однако любая прикладная среда высокого уровня, использующая мониторы, преобразует монитор в семафор запросов (или, в зависимости от вашей ОС и особенностей языка, запросов мьютекса) в скомпилированном байт-коде.

Семафоры реализованы на уровне операционной системы и / или оборудования, и языки более высокого уровня связываются с ними. На уровне ОС они «гарантированно» являются атомарными. То есть любая программа, получающая семафор, гарантированно будет единственной, которая делает это в тот момент. Если две программы или два потока в программе пытаются получить блокировку одновременно, одна пойдет первой (и будет успешной), а другая пойдет второй (и потерпит неудачу).

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

В результате, как кодировщик приложения, вы можете смело предполагать, что «lock (objLock)» будет атомарным вызовом независимо от того, сколько процессоров вы подключаете к своей системе.

1 голос
/ 10 октября 2010

Вас беспокоит именно то, почему нам нужен специальный механизм, например lock, и мы не можем просто использовать логический флаг.

Решение вашей «одновременной» проблемы заключается в алгоритме, который используется lock (который вызывает Monitor.Enter()). Он включает в себя барьеры памяти и знание механики памяти очень низкого уровня, чтобы гарантировать, что никакие 2 потока не смогут получить блокировку одновременно.

Примечание. Я говорю только о .NET, а не о Java.

...