1. Неблокирующий алгоритм
Неблокирующие алгоритмы — это параллельные алгоритмы, которые могут безопасно создавать свои потоки не посредством создания блокировок, а посредством низкоуровневых аппаратных форм атомарности, таких как сравнения и замены. Неблокирующие алгоритмы чрезвычайно сложно разработать и реализовать, но они могут обеспечить более высокую пропускную способность и лучшую защиту от проблем выживания, таких как взаимоблокировки и инверсия приоритетов. Для замены блокировок используйте низкоуровневые атомные машинные инструкции, такие как сравнение и замена (CAS).
2. Пессимистическая технология
Исключительная блокировка — это пессимистический метод. Он предполагает, что реализуется худший сценарий (если блокировка не заблокирована, другие потоки уничтожат состояние объекта), и даже если худший сценарий не произойдет, состояние объекта все равно будет защищено. замок.
3. Оптимистичная технология
Мониторинг конфликта зависимостей. Сначала обновите. Если во время мониторинга возникает конфликт, откажитесь от обновления и повторите попытку, в противном случае обновление будет успешным. Теперь процессоры имеют атомарные инструкции чтения-изменения-записи, такие как сравнение и замена (CAS, сравнение). -и- поменять местами).
4. Работа CAS
CAS имеет 3 операнда: значение памяти V, старое ожидаемое значение A и новое значение, подлежащее изменению B. Если и только если ожидаемое значение A и значение памяти V совпадают, измените значение памяти V на B, иначе ничего не делайте. Типичный шаблон использования CAS: сначала прочитайте A из V и вычислите новое значение B на основе A, а затем используйте CAS для атомарного изменения значения V с A на B (до тех пор, пока ни один поток не изменит значение V). в течение этого периода) значение до другого значения).
Листинг 3. Код, иллюстрирующий поведение (но не производительность) операции сравнения и замены. Скопируйте приведенный ниже код:
общественный класс SimulatedCAS {
частное целое значение;
общедоступный синхронизированный int getValue () {возвращаемое значение};
общедоступная синхронизированная int CompareAndSwap (int ожидаемое значение, int newValue) {
int oldValue = значение;
если (значение == ожидаемое значение)
значение = новое значение;
вернуть старое значение;
}
}
Листинг 4. Использование сравнения и обмена для реализации кода копирования счетчика. Код выглядит следующим образом:
общественный класс CasCounter {
частное значение SimulatedCAS;
общественный int getValue() {
возвращаемое значение.getValue();
}
публичный int приращение() {
int oldValue = value.getValue();
while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue)
oldValue = value.getValue();
вернуть старое значение + 1;
}
}
5. Атомарные переменные
Атомарные переменные поддерживают операции атомарного обновления без защиты блокировок, а базовый уровень реализуется с использованием CAS. Всего существует 12 атомарных переменных, которые можно разделить на 4 группы: скалярный класс, класс обновления, класс массива и класс составной переменной. Наиболее часто используемые атомарные переменные — это скалярные классы: AtomicInteger, AtomicLong, AtomicBoolean и AtomicReference. CAS поддерживается для всех типов.
6. Сравнение производительности: блокировки и атомарные переменные
В условиях конкуренции с низким и средним уровнем конкуренции атомарные переменные могут обеспечить высокую масштабируемость, а производительность атомарных переменных превышает производительность блокировок при конкуренции высокой интенсивности, блокировки могут более эффективно избегать конфликтов, а производительность блокировок превысит производительность атомарных; переменные. Но в более реалистичной практической ситуации производительность атомарных переменных превысит производительность блокировок.