Подтвердить что ты не робот

Java Concurrency: CAS против блокировки

Я читаю книгу Java Concurrency на практике. В главе 15 речь идет о неблокирующих алгоритмах и методе сравнения и свопинга (CAS).

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Относительная скорость операций в основном не является проблемой. Важна разница в масштабируемости между алгоритмами блокировки и неблокирования. И если вы работаете в 1 или 2 ядрах, перестаньте думать о таких вещах.

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

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

Если вы ищете сравнение в реальном мире, вот один. Наше приложение имеет две (2) темы: 1) поток чтения для захвата сетевого пакета и 2) потребительский поток, который принимает пакет, подсчитывает его и сообщает статистику.

Тема № 1 обменивает один пакет за раз с потоком # 2

Результат # 1 - использует пользовательский обмен на основе CAS с использованием тех же принципов, что и SynchronousQueue, где наш класс называется CASSynchronousQueue:

30,766,538 packets in 59.999 seconds ::  500.763Kpps, 1.115Gbps 0 drops
libpcap statistics: recv=61,251,128, drop=0(0.0%), ifdrop=0

Результат №2 - при замене нашей реализации CAS стандартным java SynchronousQueue:

8,782,647 packets in 59.999 seconds ::  142.950Kpps, 324.957Mbps 0 drops 
libpcap statistics: recv=69,955,666, drop=52,369,516(74.9%), ifdrop=0

Я не думаю, что разница в производительности не может быть более ясной.