ThreadLocal убивает 4 вопроса

Java Spring

Никакой суеты, просто подавайте.

Теги: [различные уровни] [Java] [исходный код]

1. спросить

Серия из четырех вопросов:

  • Принцип ThreadLocal?
  • Причина утечки памяти?
  • Вы использовали InheritableThreadLocal?
  • Что такое FastThreadLocal Netty?

2. Анализ

ThreadLocal часто используется в качестве основного метода программирования для достижения «закрытия потока». Например, традиционный формат SimpleDateFormat не является потокобезопасным. Если вы объявите ее как глобальную переменную, это вызовет путаницу во времени в параллельной среде. Хорошим решением является использование ThreadLocal.

ThreadLocal очень широко используется. Например, через него реализовано управление транзакциями Spring. Но у него есть и некоторые слабости, он не может быть прозрачно передан (не может быть получен дочерними потоками), поэтому родился InheritableThreadLocal, или даже более продвинутая библиотека инкапсуляции.

3. Ответ

3.1 Принцип ThreadLocal?

Глядя на исходный код, не трудно ответить. Как показано ниже (это изображение проще всего понять), ThreadLocal'sgetиremoveметод, является не чем иным, как ярлыком для использования. Его реальные данные существуют в структуре под названием ThreadLocalMap в потоке.

Значение ThreadLocal будет распределено по n потокам в зависимости от потока. Итак, чтобы получить значение Threadlocal, нужно выполнить два шага.

  • Первый шаг, согласно приобретению потоков карты
  • Вторая часть получает значение из Карты в соответствии с собой, так что это Ключ Карты.

Это не имеет никакого смысла. Это структура данных, которая заботится о привычках кодирования.

3.2 Каковы причины утечек памяти?

Строго говоря, у ThreadLocal нет проблем с утечкой памяти. Если есть, вы забыли выполнить метод удаления. Это вызвано неправильным использованием.

Это согласуется с некоторыми другими проблемами утечки памяти, такими как:

  • поток не закрыт
  • соединение не разорвано
  • злоупотребление статической картой

Почему возникает проблема с утечкой?

Если вы не вызовете метод удаления, значение, соответствующее ThreadLocal, будет существовать до тех пор, пока текущий поток не будет уничтожен.

Как мы все знаем, жизненный цикл потока относительно долог, и пул потоков, который обычно используется сейчас, продлит жизнь потока. Не удалить, конечно, не освободить. Это не имеет ничего общего с тем, является ли Key слабой ссылкой или нет.

В данном случае, является ли это проблемой утечки или нет, это вопрос формулировки. Процесс собеседования — это обсуждение, а не обязательно стандартный ответ.

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

3.3 Использовали ли вы InheritableThreadLocal?

InheritableThreadLocal используется при передаче значений между родительским и дочерним потоками, что решает проблему, заключающуюся в том, что threadlocal не может передавать значения между родительским и дочерним потоками.

По сути, это по-прежнему достигается с помощью Thread. Копирование атрибутов осуществляется через две Карты.

/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

Не слишком радуйтесь В случае использования пулов потоков, поскольку потоки кэшируются, потоки кэшируются и используются повторно. В настоящее время передача контекста отношения родительского и дочернего потоков не имеет значения.

Дополнительный вопрос: как вы это решили?

У Али здесь библиотека,GitHub.com/Alibaba/Вдруг…В частности, обратитесь к переменной, совместно используемой между потоками. Али Если вы столкнетесь, это может лизнуть путь.

3.4 Что такое FastThreadLocal Netty

Теперь, когда в Java есть класс ThreadLocal, почему Netty сама создала структуру под названием FastThreadLocal?

Давайте сначала посмотрим на реализацию ThreadLocal.

В классе Thread есть переменная-член threadLocals, в которой хранится вся пользовательская информация, связанная с этим потоком. Определение этой переменной находится в классе Thread, а операция — в классе ThreadLocal.

Проблема заключается в классе ThreadLocalMap, хотя он и называется Map, он не реализует интерфейс Map. Как показано на рисунке, при перехэшировании ThreadLocalMap не использует метод массив + связанный список + красно-черное дерево, аналогичный HashMap, а использует только массив и использует метод открытой адресации (в случае конфликта поиск по очереди до свободного положения) , что очень неэффективно.

Поскольку Netty использует ThreadLocal очень часто, Netty он был настроен в специальных проектах. Причина это быстро, поскольку основные структуры данных для выполнения статьи, используя постоянный индекс для позиционирования элементов вместо использования алгоритма обнаружения JDK по умолчанию.

Базовый InternalThreadLocalMap также соответствующим образом оптимизирует кэш-линию.

4. Расширение

"Нижний"Твоя тоже моя. 3 случая ко многопоточности, прозрачная передача локальных переменных

Выше есть статья о переменной прозрачной передаче, более подробная, вы можете прочитать ее.

Об авторе:Мисс сестра вкус(xjjdog), публичная учетная запись, которая не позволяет программистам идти в обход. Сосредоточьтесь на инфраструктуре и Linux. Десять лет архитектуры, десятки миллиардов ежедневного трафика, обсуждение с вами мира высокой параллелизма, дающие вам другой вкус. Мой личный WeChat xjjdog0, добро пожаловать в друзья для дальнейшего общения.​