Что так плохо с локальными потоками - PullRequest
21 голосов
/ 17 декабря 2009

Кажется, что все в мире Django ненавидят локальные потоки (http://code.djangoproject.com/ticket/4280, http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser). Я читал эссе Армина об этом (http://lucumr.pocoo.org/2006/7/10/why-i-cant-stand-threadlocal-and-others),, но большая часть его зависит от локальных потоков, потому что он неэлегантный) .

У меня есть сценарий, где theadlocals сделает вещи значительно проще. (У меня есть приложение, в котором у людей будут субдомены, поэтому все модели должны иметь доступ к текущему субдомену, и передача их из запросов не стоит того, если единственная проблема с локальными потоками состоит в том, что они неэлегентны или делают хрупкими код.)

Кроме того, многие Java-фреймворки часто используют локальные потоки, так как их случай отличается от Python / Django?

Ответы [ 5 ]

22 голосов
/ 17 декабря 2009

Я избегаю такого рода использования локальных потоков, потому что это вводит неявную нелокальную связь. Я часто использую модели во всех видах, не ориентированных на HTTP (команды локального управления, импорт / экспорт данных и т. Д.). Если я получу доступ к некоторым данным по локальным потокам в models.py, теперь мне нужно будет найти какой-нибудь способ, чтобы они всегда были заполнены, когда я использую свои модели, и это может быть довольно уродливо.

На мой взгляд, более явный код более понятен и удобен в обслуживании. Если для работы модельного метода требуется субдомен, то этот факт должен стать очевидным, если метод примет этот субдомен в качестве параметра.

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

18 голосов
/ 17 декабря 2009

Я не думаю, что с локальными потоками что-то не так - да, это глобальная переменная, но, кроме того, это обычный инструмент. Мы используем его как раз для этой цели (хранение модели поддоменов в контексте, глобальном для текущего запроса от промежуточного программного обеспечения), и оно отлично работает.

Итак, я говорю, используйте правильный инструмент для работы, в этом случае локальные потоки делают ваше приложение намного более элегантным, чем передача модели субдомена во всех методах модели (не говоря уже о том, что это даже не всегда возможно - когда переопределяют методы менеджера django для ограничения запросов по поддомену, например, вы не можете передать что-либо дополнительно в get_query_set - так что threadlocals - естественный и единственный ответ).

3 голосов
/ 17 декабря 2009

Кроме того, многие Java-фреймворки, похоже, часто используют локальные потоки, так как их случай отличается от Python / Django?

Интерпретатор CPython имеет глобальную блокировку интерпретатора (GIL), которая означает, что интерпретатор может выполнять только один поток Python в любой момент времени. Мне не ясно, что реализация интерпретатора Python обязательно должна использовать более одного потока операционной системы для достижения этой цели, хотя на практике это делает CPython.

Основной механизм блокировки Java - через блокировки монитора объектов. Это децентрализованный подход, который позволяет использовать несколько параллельных потоков на многоядерных и / или многопроцессорных процессорах, но также создает гораздо более сложные проблемы синхронизации, с которыми программист должен иметь дело.

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

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

Программист CPython также имеет возможность кодировать критический код производительности в вызываемый Python код C или C ++, где ограничение GIL не применяется. Технически Java-программист имеет аналогичную опцию через JNI, но это справедливо или ошибочно считается менее приемлемым в Java, чем в Python.

2 голосов
/ 17 декабря 2009

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

Почему передавать его из запроса не стоит? Почему бы вам не сохранить его в сеансе или профиле пользователя?

Разница с Java заключается в том, что веб-разработка гораздо более динамична, чем в мире Python / PERL / PHP / Ruby, поэтому люди привыкли к различным контекстам и тому подобному. Я не думаю, что это является преимуществом, но вначале кажется, что так оно и есть.

0 голосов
/ 22 января 2012

Я обнаружил, что использование ThreadLocal является отличным способом для внедрения Dependency Injection в среде HTTP-запросов / ответов (т.е. любого веб-приложения). Вы просто устанавливаете фильтр сервлета, чтобы «вставить» нужный вам объект в поток при получении запроса и «удалить» при возврате ответа.

Это DI умного человека без всякого уродства XML, без MB Spring Jars (не говоря уже о его кривой обучения) и без всякой загадочной повторяющейся ерунды @annotation и потому что он по отдельности не вводит много экземпляров объекта с помощью зависимости, это, вероятно, чертовски намного быстрее и использует меньше памяти.

Это сработало настолько хорошо, что мы открыли источник нашего фильтра exPOJO, который может внедрить сеанс Hibernate или JDO PersistenceManager с использованием ThreadLocal:

http://www.expojo.com

...