C # ThreadStaticAttribute отмеченные поля автоматически освобождаются, когда поток умирает? - PullRequest
18 голосов
/ 16 января 2010

Я обнаружил ThreadStaticAttribute, и у меня много вопросов по этому поводу: все мои предыдущие зависимые от потока статические данные были реализованы в виде статического словаря, которым TKey является Thread, и когда я хотел получить к нему доступ, я использовал Thread.CurrentThread, и это работает. Но это требует заботы, потому что, если поток умирает, я должен удалить соответствующую запись из словаря. И еще мне нужно учитывать безопасность потоков и множество других вопросов.

С помощью ThreadStaticAttribute все эти вопросы, кажется, решаются, но я должен быть уверен в этом. Мои вопросы: мне нужно удалить экземпляр, удерживаемый помеченными полями ThreadStaticAttribute, каким-то образом, прежде чем поток умирает? Где хранится информация об этом поле? Это экземпляр объекта Thread или что-то в этом роде, так что, когда он больше не используется, сборщик мусора автоматически его отбрасывает? Есть ли штрафы за производительность? Какие? Это быстрее, чем использовать коллекцию Keyed, как я делал?

Пожалуйста, мне нужно уточнить, как работает ThreadStaticAttribute.

Спасибо.

Ответы [ 2 ]

11 голосов
/ 16 января 2010

Нет, вам не нужно удалять экземпляры справки по значениям в поле, которое помечено ThreadStatic. Сборщик мусора автоматически поднимет их, когда поток и объект более недоступны для корневых объектов.

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

Относительно того, где на самом деле хранится это поле, оно несколько не имеет значения. Все, что вам нужно беспокоиться, это то, что он будет вести себя как любой другой объект в .Net. Единственными двумя поведенческими различиями являются

  1. Поле будет ссылаться на другое значение для каждого потока доступа.
  2. Инициализатор для поля будет запущен только один раз (на практике, иметь плохую идею).
6 голосов
/ 16 января 2010

Пометка статической переменной-члена как [ThreadStatic] указывает компилятору размещать ее в области памяти потока (например, там, где выделен стек потока), а не в области глобальной памяти. Таким образом, каждый поток будет иметь свою собственную копию (которая гарантированно будет инициализирована значением по умолчанию для этого типа, например, null, 0, false и т. Д .; не используйте встроенные инициализаторы, поскольку они будут инициализировать его только для одного потока ).

Итак, когда поток уходит, его область памяти освобождается, освобождая ссылку. Конечно, если это требует немедленного удаления (открытия потоков файлов и т. Д.), А не ожидания фоновой сборки мусора, вам может потребоваться сделать это до выхода из потока.

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

Исправление: С тех пор я слышал, что доступ к переменным ThreadStatic несколько медленнее, чем к обычным статическим переменным. Я не уверен, что это даже на самом деле быстрее, чем доступ к коллекции ключей, но он позволяет избежать проблем сирот (что было вашим вопросом) и необходимости блокировки для обеспечения безопасности потоков, что усложнит подход к коллекции ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...