2009-09-25 3 views
6
import threading 

mydata = threading.local() 

def run(): 
    # When will the garbage collector be able to destroy the object created 
    # here? After the thread exits from ``run()``? After ``join()`` is called? 
    # Or will it survive the thread in which it was created, and live until 
    # ``mydata`` is garbage-collected? 
    mydata.foo = object() 

t = threading.Thread(target=run) 
t.start() 
t.join() 

ответ

3

Марк был почти сразу же - по существу "MYDATA" будет хранить ссылки на все ТЛ переменные в ней, независимо от нити они были созданы из. Для остроумие ...:

import threading 
import gc 

mydata = threading.local() 

class x: 
    def __del__(self): 
     print "x got deleted!" 

def run(): 
    mydata.foo = x() 

t = threading.Thread(target=run) 
print "t created" 
gc.collect() 
t.start() 
print "t started" 
gc.collect() 
del mydata 
print "mydata deleted" 
gc.collect() 
t.join() 
print "t joined" 
gc.collect() 
print "Done!" 

Издает:

t created 
t started 
x got deleted! 
mydata deleted 
t joined 
Done! 

дс фактически не играет никакой роли здесь в CPython, так что вы можете упростить код до:

import threading 

mydata = threading.local() 

class x: 
    def __init__(self): 
     print "x got created!" 
    def __del__(self): 
     print "x got deleted!" 

def run(): 
    mydata.foo = x() 

t = threading.Thread(target=run) 
print "t created" 
t.start() 
print "t started" 
del mydata 
print "mydata deleted" 
t.join() 
print "t joined" 
print "Done!" 

и по-прежнему видеть ...:

t created 
x got created! 
t started 
x got deleted! 
mydata deleted 
t joined 
Done! 
0

Сделав пару простых изменений в вашу программу и принуждать сбор мусора после каждого шага резьбы, кажется, что foo не может быть собрана, пока программа не будет завершена, - другими словами, после нить выходит объема.

import threading 
import gc 

mydata = threading.local() 

class x: 
    def __del__(self): 
     print "x got deleted!" 

def run(): 
    mydata.foo = x() 

t = threading.Thread(target=run) 
print "t created" 
gc.collect() 
t.start() 
print "t started" 
gc.collect() 
t.join() 
print "t joined" 
gc.collect() 
print "Done!" 

выход (с использованием Python 2.6, Windows):

 
>C:\temp\py\t.py 
t created 
t started 
t joined 
Done! 
x got deleted! 
+0

Хороший анализ, но недостающий бит заключается в том, что _mydata_ уходит, что вам нужно - мне нужно открыть новый ответ, чтобы отобразить форматированный код, но суть такая же, как ваша. –

1

Спасибо! Кажется, что программа Марк ведет себя по-разному в CPython 2.5 и 2.6:

import threading 
import gc 
import platform 

print "Python %s (%s)" % (platform.python_version(), " ".join(platform.python_build())) 

mydata = threading.local() 

class x: 
    def __del__(self): 
     print "x got deleted!" 

def run(): 
    mydata.foo = x() 

t = threading.Thread(target=run) 
print "t created" 
gc.collect() 
t.start() 
print "t started" 
gc.collect() 
del mydata 
print "mydata deleted" 
gc.collect() 
t.join() 
print "t joined" 
gc.collect() 
print "Done!" 

Издает (под Ubuntu 8.04 i386):

Python 2.5.2 (r252:60911 Jul 31 2008 19:40:22) 
t created 
t started 
mydata deleted 
x got deleted! 
Exception in thread Thread-1: 
Traceback (most recent call last): 
    File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner 
    self.run() 
    File "/usr/lib/python2.5/threading.py", line 446, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "./x.py", line 14, in run 
    mydata.foo = x() 
NameError: global name 'mydata' is not defined 

t joined 
Done! 

И:

Python 2.6.2 (r262:71600 Sep 19 2009 17:24:20) 
t created 
t started 
x got deleted! 
mydata deleted 
t joined 
Done! 
3

Вот мой ответ, так как Я не вижу вывода в предыдущих ответах.

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

import time 
import threading 
import gc 

data = threading.local() 

class Resource(object): 
    def __init__(self): 
     self.name = threading.currentThread().name 
     print 'create: %s' % self.name 

    def __del__(self): 
     print 'delete: %s' % self.name 

def access_thlocal(): 
    data.key = Resource() 

for i in range(0, 10): 
    threading.Thread(target=access_thlocal).start() 
time.sleep(1) 
print "Triggering GC" 
gc.collect() 
time.sleep(1) 

Выход:

create: Thread-1 
create: Thread-2 
delete: Thread-1 
create: Thread-3 
delete: Thread-2 
create: Thread-4 
delete: Thread-3 
create: Thread-5 
delete: Thread-4 
create: Thread-6 
delete: Thread-5 
create: Thread-7 
delete: Thread-6 
create: Thread-8 
delete: Thread-7 
create: Thread-9 
delete: Thread-8 
create: Thread-10 
delete: Thread-9 
Triggering GC 
delete: Thread-10 

Как вы можете видеть, удалить, кажется, произойдет, как только поток умирает.

Смежные вопросы