Типичные ошибки многопоточного программирования с коллекциями
ConcurrentModificationException: Анатомия ошибки
ConcurrentModificationException возникает при обнаружении структурных изменений коллекции во время итерации.
Механизм основан на сравнении счетчика модификаций:
Типичные сценарии возникновения
Сценарий 1: Модификация во время итерации в одном потоке
Сценарий 2: Конкурентная модификация в разных потоках
NullPointerException в многопоточном контексте
NullPointerException в многопоточных сценариях часто является следствием race conditions, а не просто нулевых ссылок:
Классический антипаттерн с небезопасной публикацией:
Разные коллекции по-разному обрабатывают null:
#Java #для_новичков #beginner #immutability #Collection #synchronizedList #ConcurrentHashMap #CopyOnWriteArrayList
ConcurrentModificationException: Анатомия ошибки
ConcurrentModificationException возникает при обнаружении структурных изменений коллекции во время итерации.
Механизм основан на сравнении счетчика модификаций:
// Внутренний механизм ArrayList
protected transient int modCount = 0;
// В итераторе
int expectedModCount = modCount;
void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Типичные сценарии возникновения
Сценарий 1: Модификация во время итерации в одном потоке
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String item : list) { // Создается итератор
if (item.equals("B")) {
list.remove(item); // modCount++ → исключение!
}
}Сценарий 2: Конкурентная модификация в разных потоках
// Поток 1
for (String item : sharedList) {
process(item); // Итерация
}
// Поток 2
sharedList.add("new"); // ConcurrentModificationException в потоке 1
NullPointerException в многопоточном контексте
NullPointerException в многопоточных сценариях часто является следствием race conditions, а не просто нулевых ссылок:
public class UnsafeCache {
private Map<String, Data> cache = new HashMap<>();
public Data get(String key) {
Data data = cache.get(key);
if (data == null) {
data = loadData(key); // Дорогая операция
cache.put(key, data); // Race condition!
}
return data; // Может вернуть null
}
}Классический антипаттерн с небезопасной публикацией:
public class BrokenSingleton {
private static Data instance;
public static Data getInstance() {
if (instance == null) { // Первая проверка (без синхронизации)
synchronized (BrokenSingleton.class) {
if (instance == null) { // Вторая проверка
instance = new Data(); // Небезопасная публикация!
}
}
}
return instance; // Может вернуть частично инициализированный объект
}
}Разные коллекции по-разному обрабатывают null:
// ConcurrentHashMap: запрещает null
ConcurrentHashMap<String, String> chm = new ConcurrentHashMap<>();
chm.put("key", null); // NullPointerException
// CopyOnWriteArrayList: разрешает null
CopyOnWriteArrayList<String> cowal = new CopyOnWriteArrayList<>();
cowal.add(null); // Допустимо
// Collections.synchronizedList: зависит от оборачиваемой коллекции
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
syncList.add(null); // Допустимо для ArrayList
#Java #для_новичков #beginner #immutability #Collection #synchronizedList #ConcurrentHashMap #CopyOnWriteArrayList
👍2
Race conditions и data races
Race condition: Неправильное поведение из-за непредсказуемого порядка выполнения
Data race: Одновременный доступ к shared memory без proper synchronization
Пример race condition
Пример data race
Deadlock, livelock и starvation
Deadlock с коллекциями
Livelock в конкурентных алгоритмах
Starvation в synchronized коллекциях
#Java #для_новичков #beginner #immutability #Collection #synchronizedList #ConcurrentHashMap #CopyOnWriteArrayList
Race condition: Неправильное поведение из-за непредсказуемого порядка выполнения
Data race: Одновременный доступ к shared memory без proper synchronization
Пример race condition
public class Counter {
private int count;
public void increment() {
count++; // Неатомарная операция: read-modify-write
}
}
// Два потока вызывают increment() 1000 раз каждый
// Ожидаемый результат: 2000
// Фактический результат: что угодно между 1000 и 2000Пример data race
public class VisibilityProblem {
private boolean ready = false;
private int value;
// Поток 1
public void writer() {
value = 42;
ready = true; // Без happens-before!
}
// Путок 2
public void reader() {
if (ready) {
System.out.println(value); // Может увидеть 0 вместо 42!
}
}
}Deadlock, livelock и starvation
Deadlock с коллекциями
// Классический deadlock с synchronizedList
List<String> list1 = Collections.synchronizedList(new ArrayList<>());
List<String> list2 = Collections.synchronizedList(new ArrayList<>());
// Поток 1
synchronized (list1) {
synchronized (list2) { // Ждет list2
// Критическая секция
}
}
// Путок 2 (обратный порядок)
synchronized (list2) {
synchronized (list1) { // Ждет list1 → DEADLOCK!
// Критическая секция
}
}
Livelock в конкурентных алгоритмах
public class LivelockExample {
private final ConcurrentHashMap<String, Boolean> locks =
new ConcurrentHashMap<>();
public void process(String key) {
// Бесконечные попытки захвата "локера"
while (!locks.putIfAbsent(key, true)) {
Thread.yield(); // Livelock: постоянно уступаем, но не прогрессируем
}
try {
// Работа с ресурсом
} finally {
locks.remove(key);
}
}
}Starvation в synchronized коллекциях
// Поток, постоянно читающий
synchronized (sharedList) {
// Долгая операция чтения
processAllElements(sharedList);
}
// Другие потоки не могут получить доступ для записи
// → Starvation писателей
#Java #для_новичков #beginner #immutability #Collection #synchronizedList #ConcurrentHashMap #CopyOnWriteArrayList
👍2
Что выведет код?
#Tasks
import java.util.concurrent.*;
public class Task301225 {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("a", 1);
Integer result = map.computeIfAbsent("b", k -> {
map.put("b", 2);
return map.get("b");
});
System.out.println(result);
System.out.println(map.get("b"));
}
}
#Tasks
👍1
👍1
Вопрос с собеседований
Почему volatile не заменяет synchronized?🤓
Ответ:
volatile гарантирует видимость изменений, но не атомарность составных операций.
Например, count++ небезопасен даже с volatile. synchronized обеспечивает и видимость, и взаимное исключение, но дороже по производительности.
#собеседование
Почему volatile не заменяет synchronized?
Ответ:
Например, count++ небезопасен даже с volatile. synchronized обеспечивает и видимость, и взаимное исключение, но дороже по производительности.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История IT-технологий сегодня — 31 декабря
ℹ️ Кто родился в этот день
Не нашел(
🌐 Знаковые события
1879 – Томас Эдисон впервые демонстрирует публике лампы накаливания в Менло-Парке, штат Нью-Джерси.
1983 – Компания AT&T Bell System была расформирована правительством Соединенных Штатов .
#Biography #Birth_Date #Events #31Декабря
Не нашел(
1879 – Томас Эдисон впервые демонстрирует публике лампы накаливания в Менло-Парке, штат Нью-Джерси.
1983 – Компания AT&T Bell System была расформирована правительством Соединенных Штатов .
#Biography #Birth_Date #Events #31Декабря
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Друзья и подписчики!
Вот и пришёл 2026 год🎄
Нам вновь даны 365 дней — для достижения целей и задач, для реализации смелых надежд и по-настоящему больших планов.
В этот день, который символизирует начало нового года, особенно приятно осознавать, что мы вместе. 🤝
Да, у нас небольшое и не самое активное сообщество, но я по-прежнему верю: нас объединяет стремление становиться лучше и сильнее, профессионально расти, быть более востребованными и со временем — действительно незаменимыми специалистами.
Я искренне благодарен каждому, кто участвует в жизни канала: ставит лайки, пишет комментарии и приходит на встречи.❤️
Именно для Вас канал продолжает жить и развиваться — без этого он давно бы умер.
Я твёрдо уверен, что когда наши парни дожмут врага на фронте и мы победим (а это неизбежно)💪 , компании перестанут жить в режиме неопределённости. Страх сменится расчётом и рынок начнёт постепенно оживать. Вакансий станет больше, требования — адекватнее, а ценность реальной экспертизы снова выйдет на первый план.
И именно те, кто уже сегодня системно наращивает знания и практику, окажутся максимально востребованными в этот момент.
И именно поэтому, несмотря на все штормы и бури рынка вакансий, засилье автоматических фильтров, роботов и ЧСВшных HR, я хочу, чтобы в 2026 году каждый из вас окончательно и бесповоротно покорил Java и получил тот самый оффер на 500k в секунду😎
Пусть это звучит иронично, но каждое усилие, каждый разобранный класс и каждая изученная библиотека реально приближают вас к этой цели.
В первые минуты нового года, оставляя за спиной трудности и сомнения, хочется пожелать вам простых, но важных вещей — удачи и терпения.👌
Удача пригодится при откликах на вакансии, а терпение — при подготовке и прохождении собеседований.😄
Желаю всем здоровья, счастья, любви близких и надёжной поддержки друзей.
Пусть 2026 год принесёт не только профессиональные достижения, но и внутреннюю гармонию, ощущение устойчивости и уверенности в выбранном пути.
С Новым годом!🌲
Вот и пришёл 2026 год
Нам вновь даны 365 дней — для достижения целей и задач, для реализации смелых надежд и по-настоящему больших планов.
В этот день, который символизирует начало нового года, особенно приятно осознавать, что мы вместе. 🤝
Да, у нас небольшое и не самое активное сообщество, но я по-прежнему верю: нас объединяет стремление становиться лучше и сильнее, профессионально расти, быть более востребованными и со временем — действительно незаменимыми специалистами.
Я искренне благодарен каждому, кто участвует в жизни канала: ставит лайки, пишет комментарии и приходит на встречи.
Именно для Вас канал продолжает жить и развиваться — без этого он давно бы умер.
Я твёрдо уверен, что когда наши парни дожмут врага на фронте и мы победим (а это неизбежно)
И именно те, кто уже сегодня системно наращивает знания и практику, окажутся максимально востребованными в этот момент.
И именно поэтому, несмотря на все штормы и бури рынка вакансий, засилье автоматических фильтров, роботов и ЧСВшных HR, я хочу, чтобы в 2026 году каждый из вас окончательно и бесповоротно покорил Java и получил тот самый оффер на 500k в секунду
Пусть это звучит иронично, но каждое усилие, каждый разобранный класс и каждая изученная библиотека реально приближают вас к этой цели.
В первые минуты нового года, оставляя за спиной трудности и сомнения, хочется пожелать вам простых, но важных вещей — удачи и терпения.
Удача пригодится при откликах на вакансии, а терпение — при подготовке и прохождении собеседований.
Желаю всем здоровья, счастья, любви близких и надёжной поддержки друзей.
Пусть 2026 год принесёт не только профессиональные достижения, но и внутреннюю гармонию, ощущение устойчивости и уверенности в выбранном пути.
С Новым годом!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11🍾3👍1👎1🤓1🆒1 1
История IT-технологий сегодня — 01 января
ℹ️ Кто родился в этот день
Ива́н Алексе́евич Вышнегра́дский (20 декабря 1831 [1 января 1832], Вышний Волочёк — 25 марта [6 апреля] 1895, Санкт-Петербург) — русский учёный-механик и государственный деятель. Основоположник теории автоматического регулирования, почётный член Петербургской АН (1888)
🌐 Знаковые события
1801 – Джузеппе Пиацци открывает Цереру , самый большой и первый известный объект в поясе астероидов.
1983 — ARPANET сменила основной протокол с NCP на TCP/IP, что и привело к появлению современного Интернета.
#Biography #Birth_Date #Events #01Января
Ива́н Алексе́евич Вышнегра́дский (20 декабря 1831 [1 января 1832], Вышний Волочёк — 25 марта [6 апреля] 1895, Санкт-Петербург) — русский учёный-механик и государственный деятель. Основоположник теории автоматического регулирования, почётный член Петербургской АН (1888)
1801 – Джузеппе Пиацци открывает Цереру , самый большой и первый известный объект в поясе астероидов.
1983 — ARPANET сменила основной протокол с NCP на TCP/IP, что и привело к появлению современного Интернета.
#Biography #Birth_Date #Events #01Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История IT-технологий сегодня — 02 января
ℹ️ Кто родился в этот день
Линн Конвей (англ. Lynn Conway; 10 января 1938, Маунт-Вернон, штат Нью-Йорк, США — 9 июня 2024, Джэксон[англ.], Мичиган, США) — американская компьютерная учёная, инженер-электроник, изобретательница, работала в IBM и внесла заметный вклад в создание суперскалярной архитектуры компьютеров.
🌐 Знаковые события
1959 — в СССР запущена первая автоматическая межпланетная станция «Луна-1».
#Biography #Birth_Date #Events #02Января
Линн Конвей (англ. Lynn Conway; 10 января 1938, Маунт-Вернон, штат Нью-Йорк, США — 9 июня 2024, Джэксон[англ.], Мичиган, США) — американская компьютерная учёная, инженер-электроник, изобретательница, работала в IBM и внесла заметный вклад в создание суперскалярной архитектуры компьютеров.
1959 — в СССР запущена первая автоматическая межпланетная станция «Луна-1».
#Biography #Birth_Date #Events #02Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2