Многопоточность

Переменные volatile

При старте потока для него создаётся свой стек вызовов. Сколько запущенных потоков, столько и стеков. Каждый поток, из соображений производительности, копирует переменные из основной памяти в свой стек, получая их локальную копию. Другими словами, каждый поток кэширует себе переменные. Поток не имеет доступа к копиям переменных, которые были закэшированы другими потоками. ... Читать дальше »

Callable, который не возвращает значение

Метод run() интерфейса Runnable отличается от метода call() интерфейса Callable тем, что он не возвращает никакого значения и не выбрасывает исключения. Однако, если потребуется, чтобы метод call() тоже не возвращал значение, то в качестве параметризованного параметра можно передать Void. ... Читать дальше »

Синхронизация на разных объектах

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

Future и FutureTask

Future<V> - это интерфейс, представляющий результат асинхронного вычисления - тот результат, который будет получен в будущем после выполнения задачи. Методы, выполнение которых занимает довольно много времени, хорошие кандидаты для асинхронной обработки. Использование интерфейса Future позволяет потоку не простаивать во время ожидания завершения метода, инкапсулированного в Future, а выполнять какую-нибудь полезную работу.

Класс FutureTask<V> - реализация интерфейса Future<V>. ... Читать дальше »

ThreadLocal-переменные

ThreadLocal - это тип поля, привязанный к конкретному потоку.
Это значит, что каждый поток имеет свой собственный, индивидуально инициализируемый экземпляр ThreadLocal-переменной, доступ к которой он получает через методы get() или set(). Даже если это поле будет статическое, оно все равно у каждого потока будет своё.

Как работает ThreadLocal? У каждого потока - т.е. экземпляра класса Thread - есть ассоциированная с ним таблица ThreadLocal-переменных. Ключами таблицы являются cсылки на объекты класса ThreadLocal, а значениями - ссылки на объекты, "захваченные" ThreadLocal-переменными. ... Читать дальше »

Метод yield()

Вызов статического метода Thread.yield() сообщит планировщику, что вызвавший поток готов приостановить своё выполнение и передать управление другим потокам, но хотел бы возобновить свою работу как только это будет возможно. Планировщик, если посчитает нужным, приостановит поток, переведя его в состояние Runnable. ... Читать дальше »

Как избежать dead lock. Способ 3. Гибкий захват ресурсов

Гибкий захват ресурсов подразумевает под собой две вещи:
  1. Перед захватом ресурса выполняется проверка, не заблокирован ли он уже (try lock). Если ресурс свободен, поток его сразу захватывает.
  2. Можно указать время ожидания ресурса, по истечению которого поток продолжит свою работу. Т.о. поток не будет висеть неопределённое количество времени, а сможет выполнить какую-нибудь полезную работу. Synchronized-блоки такой возможности не дают.
... Читать дальше »

Как избежать dead lock. Способ 2. Дополнительный монитор

Когда невозможно решить какой из ресурсов нужно захватить первым, можно ввести дополнительный монитор. Тогда сначала будет захватываться этот монитор, а потом уже требуемые ресурсы, не важно в каком порядке. Если другому потоку потребуются эти же ресурсы, сначала он попытается захватить дополнительный монитор, не сможет этого сделать и перейдёт в режим ожидания. ... Читать дальше »

Как избежать dead lock. Способ 1. Приоритеты ресурсов

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

... Читать дальше »
1 2 »