Параллелизм Java: CAS по сравнению с [закрытой] блокировкой

Я читаю Книжный Параллелизм Java на практике. В главе 15 они говорят о неблокирующихся алгоритмах и методе сравнивать-и-подкачивать (CAS).

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

Для меня использование блокировок является намного более четким и легче понять и возможно еще лучше поддержать (исправьте меня, если я неправ). Мы должны действительно сфокусироваться на создании нашего параллельного кода, связанного с CAS, чем блокировки для получения лучшего повышения производительности или действительно ли устойчивости более важны?

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

69
задан Pang 8 January 2017 в 08:00
поделиться

4 ответа

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

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

41
ответ дан 24 November 2019 в 13:51
поделиться

Вы можете посмотреть числа между ConcurrentLinkedQueue и BlockingQueue . Вы увидите, что CAS заметно быстрее при умеренном (более реалистичном в реальных приложениях) конфликте потоков.

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

Чтобы ответить на ваши вопросы, да, неблокирующие потокобезопасные алгоритмы или коллекции ( ConcurrentLinkedQueue , ConcurrentSkipListMap / Set ) могут быть значительно быстрее, чем их блокирующие аналоги. Однако, как заметил Марсело, получение правильных неблокирующих алгоритмов очень сложно и требует большого внимания.

Вы должны прочитать об очереди Майкла и Скотта , это реализация очереди для ConcurrentLinkedQueue и объясняет, как обрабатывать двустороннюю, потокобезопасную, атомарную функцию с помощью одиночный CAS .

22
ответ дан 24 November 2019 в 13:51
поделиться

Есть хорошая книга, тесно связанная с темой параллелизма без блокировок: "Искусство многопроцессорного программирования" Автор: Морис Херлихи

13
ответ дан 24 November 2019 в 13:51
поделиться

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

Неблокирующие алгоритмы обычно лучше масштабируются, потому что они имеют более короткие «критические секции», чем алгоритмы на основе блокировок.

28
ответ дан 24 November 2019 в 13:51
поделиться
Другие вопросы по тегам:

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