Эта статья была написана, когда я только поступал в школу, и я откопал ее, когда сегодня разбирал черновик. Во время беспорядочного интервью в то время я записал несколько параллельных вопросов интервью, на многие из которых я не получил ответа. На данный момент я многому научился в области параллелизма.Оглядываясь назад на эти вопросы и ответы, собранные в то время, я понимаю, что они полны лазеек и очень нелепы. Право на публикацию должно быть напоминанием самому себе-Если вы не сможете продолжать совершенствоваться, вы не сможете увидеть свое глупое «я».
Когда-то во время интервью со стажерами отдела Java R&D я чаще всего слышал следующую фразу:
Как можно не изучать параллелизм в Java?
Да, действительно, после бесчисленного презрения со стороны интервьюера я понял важность параллельного программирования Java в языке Java.
Модель параллелизма
Понимание пессимистической блокировки и оптимистической блокировки и как ее реализовать, каковы методы реализации?
пессимистический замок
Пессимистическая блокировка предполагает наихудший случай (если вы не запираете дверь, нарушитель спокойствия ворвется и устроит беспорядок) и может продолжаться только в том случае, если вы гарантируете, что другие потоки не будут мешать (получив правильный замок).
Общие реализации, такие как эксклюзивные блокировки и т. д.
Более безопасный, но менее эффективный при уровне параллелизма от низкого до среднего.
оптимистическая блокировка
Оптимистическая блокировка использует механизм проверки конфликтов, чтобы определить, есть ли помехи от других потоков во время процесса обновления.Если это так, операция завершается ошибкой и может быть повторена (или нет).
Общие реализации, такие как CAS и т. д.
Частичная оптимистическая блокировка ослабляет согласованность, но эффективность значительно повышается при низком и среднем уровнях параллелизма.
параллельное программирование
Как создать поток в Java
С точки зрения прямого интерфейса фактически существует только один способ реализации интерфейса Runable, но класс Thread обеспечивает большую поддержку операций с потоками, поэтому обычной практикой является реализация интерфейса Runable, создание экземпляра и передача в конструктор класса Thread.
- Наследовать Thread и переопределить метод запуска
- Реализуйте интерфейс Runable и переопределите метод запуска.
Как Vector (HashTable) обеспечивает безопасность потоков
Украсьте каждый метод ключевым словом synchronized.
На основе ключевого слова synchronized возникают следующие проблемы.
В чем разница между синхронизированным оформлением метода и оформлением блока кода
Объекты, удерживающие замки, бывают разными:
- При оформлении метода: текущий экземпляр, на который ссылается this, удерживает блокировку
- При оформлении блока кода: Чтобы указать объект, удерживающий замок
В результате значения этих двух различны:
- Блоки синхронизированного кода могут иметь меньшую область блокировки, чем синхронизированные методы.Вообще говоря, размер области блокировки и производительность обратно пропорциональны.
- Декорированный блок кода может выбирать, какой объект блокировать, но декорированный метод может блокировать только этот объект.
Как ConcurrentHashMap обеспечивает безопасность потоков
Поточно-безопасная реализация ConcurrentHashMap отличается от HashTable:
- ConcurrentHashMap можно понимать как не хранящий HashMao напрямую, а заменяющий HashMap несколькими сегментами. Однако фактическая реализация части Map в основном такая же, как HashMap.Модуль нижнего колонтитула используется для определения сегмента, к которому принадлежит table[i], чтобы получить разные блокировки сегмента для разных сегментов.
- Каждый сегмент содержит блокировку, а сегментированная блокировка не только обеспечивает потокобезопасность, но и учитывает производительность.
Каковы способы реализации параллельного программирования в Java
Начнем с самого простого ответа, наиболее часто используемого в отрасли — это ключевой момент, а новые идеи помещаются в конец.
- синхронизированное ключевое слово
- Используйте методы wait, notify, notifyAll, унаследованные от класса Object.
- Используйте потокобезопасный API и классы коллекций:
- Используйте потокобезопасные классы коллекций, такие как Vector и HashTable.
- Используйте слабо согласованные классы коллекций, такие как ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue, предоставленные в пакете Concurrent.
- В классе Collections есть несколько статических методов, которые могут получать коллекции, полученные путем инкапсуляции несинхронизированных коллекций с помощью синхронизированных методов, таких как
List list = Collection.synchronizedList(new ArrayList())
. - Используйте атомарные переменные, volatile переменные и т.д.
- Используйте Semaphore, Latch, Barrier, Exchanger, Callable&Future, BlockingQueue и т. д., предоставленные в пакете Concurrent.
- Вручную используйте Lock для реализации управления параллелизмом на основе блокировки
- Вручную используйте Condition или AQS для реализации условного управления параллелизмом на основе очереди.
- Реализовать неблокирующий контроль параллелизма с помощью CAS, SPIN и т. д.
- Используйте неизменяемые классы
- Другие модели параллелизма не были рассмотрены.
Это приводит к следующим вопросам:
Принцип реализации ConcurrentHashMap (см. выше)
Когда происходит операция копирования CopyOnWriteArrayList?
Разница между синхронизированным списком и вектором
- В реализации synchronizedList ключевое слово synchronized изменяет блок кода, а в реализации Vector — метод.
- synchronizedList только инкапсулирует блоки кода, такие как добавление, получение, удаление и т. д., но Iterator не синхронизируется.Требуется ручная синхронизация при перемещении; Итератор также заблокирован в Векторе.
- synchronizedList может инкапсулировать все классы реализации List в синхронизированную коллекцию, и он по-прежнему содержит класс реализации List (ArrayList/LinkedList) внутри, поэтому помимо синхронизации существует почти только разница между этим классом реализации и Vector.
Насколько синхронизирована разница между декорированием метода и декорированием блока кода (см. выше)
Семафор, защелка, барьер, переключатель
Принцип реализации Exchanger, Callable&Future и очереди блокировки BlockingQueue
Алгоритм вставки ConcurrentLinkedQueue
Суть алгоритма можно свести к двум этапам:
- Сначала проверьте, является ли это промежуточным состоянием (SPIN)
- Попробуйте вставить CAS еще раз
Детали будут добавлены.
Ссылаться на:
В чем разница между методами ожидания и сна в Java?
Самая большая разница заключается в том, что ожидание освобождает блокировку во время ожидания, а сон продолжает удерживать блокировку. Ожидание обычно используется для взаимодействия между потоками, а сон обычно используется для приостановки выполнения.
Почему методы wait, notify и notifyAll не относятся к классу потока?
Основная причина заключается в том, что блокировки, предоставляемые JAVA, являются объектными, а не потоковыми, и каждый объект имеет блокировку, полученную потоком. Так как wait, notify и notifyAll являются операциями на уровне блокировки, они определены в классе Object, поскольку блокировки принадлежат объектам.
Почему методы ожидания и уведомления вызываются в синхронизированных блоках?
Java API предписывает это, и если вы этого не сделаете, ваш код выдаст исключение IllegalMonitorStateException. Другая причина заключается в том, чтобы избежать условий гонки между ожиданием и уведомлением.
Почему вы должны проверять условия ожидания в циклах?
Потоки в состоянии ожидания могут получать ложные тревоги и ложные пробуждения, и если условие ожидания не проверяется в цикле, программа завершится без выполнения условия завершения.
В чем разница между методами submit() и execute() в пуле потоков Java?
Оба метода могут отправлять задачи в пул потоков.Тип возвращаемого значения метода execute() — void, который определен в интерфейсе Executor, а метод submit() может возвращать объект Future, содержащий результат вычисления, который определен в интерфейсе ExecutorService.Он расширяет интерфейс Executor, другие классы пула потоков, такие как ThreadPoolExecutor и ScheduledThreadPoolExecutor, имеют эти методы.
В чем разница между volatile переменной и атомарной переменной?
Изменчивые переменные могут обеспечить упреждающие отношения, то есть операции записи будут выполняться до последующих операций чтения, но не гарантируют атомарности. Например, если переменная count изменена с помощью volatile, то операция count++ не является атомарной. Атомарный метод, предоставляемый классом AtomicInteger, может сделать эту операцию атомарной. Например, метод getAndIncrement() будет атомарно выполнять инкрементную операцию и добавлять единицу к текущему значению. Другие типы данных и ссылочные переменные также могут выполнять аналогичные операции.
Почему методы sleep() и yield() класса Thread статичны?
Методы sleep() и yield() класса Thread будут выполняться в текущем выполняющемся потоке. Поэтому нет смысла вызывать эти методы в других ожидающих потоках. Вот почему эти методы являются статическими. Они могут работать в текущем выполняющемся потоке и не дают программисту ошибочно подумать, что эти методы могут быть вызваны из других неработающих потоков.
Ссылка на эту статью:Синтез с высокой степенью параллелизма в Java
автор:обезьяна 007
Источник:monkeysayhi.github.io
Эта статья основана наCreative Commons Attribution-ShareAlike 4.0Выпущено по международному лицензионному соглашению, приветствуется перепечатка, вывод или использование в коммерческих целях, но авторство и ссылка на эту статью должны быть сохранены.