многопоточность: почему генераторы не являются потокобезопасными? Что происходит, когда он разделяется между потоками?

Я читаю этот вопрос, который спрашивает, являются ли генераторы потокобезопасными, и один ответ сказал:

Это не поточно-безопасный; одновременные вызовы могут чередовать и помешать локальным переменным.

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

Я новичок в многопоточности. Может ли кто-нибудь разработать пример, чтобы показать, что именно происходит, когда вы используете генератор без блокировки?

Например, у меня нет никаких проблем, если я это сделаю:

import threading def generator(): for i in data: yield i class CountThread(threading.Thread): def __init__(self, name): threading.Thread.__init__(self) self.name = name def run(self): for i in gen(): print '{0} {1}'.format(self.name, i) data = [i for i in xrange(100)] gen = generator() a = CountThread('a') b = CountThread('b') a.start() b.start() 

One Solution collect form web for “многопоточность: почему генераторы не являются потокобезопасными? Что происходит, когда он разделяется между потоками?”

Запустите этот пример.

Вы увидите, что 10 000 номеров будут «разделяться» по потокам. Вы не увидите 10 000 номеров в обоих потоках.

На самом деле, скорее всего, один поток увидит все числа.

 import threading class CountThread(threading.Thread): def __init__(self, gen): threading.Thread.__init__(self) self.gen = gen self.numbers_seen = 0 def run(self): for i in self.gen: self.numbers_seen += 1 def generator(data): for _ in data: yield data gen = generator(xrange(10000)) a = CountThread(gen) b = CountThread(gen) a.start() b.start() a.join() b.join() print "Numbers seen in a", a.numbers_seen print "Numbers seen in b", b.numbers_seen 

Фактически, если произойдет, что Python переключает потоки во время выполнения (просто используйте более высокое значение, чем 10000, например 10000000), вы получите исключение:

 Exception in thread Thread-2: Traceback (most recent call last): File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 808, in __bootstrap_inner self.run() File "test.py", line 10, in run for i in self.gen: ValueError: generator already executing 
  • Python time.sleep () vs event.wait ()
  • Как я могу использовать GIL для словаря в многопоточном приложении?
  • Тупик с протоколированием многопроцессорного / многопоточного скрипта python
  • Как поместить tcp-сервер в другой поток в python
  • Многопоточность в python
  • Как узнать, что uWSGI предпочитает процессы для потоков для балансировки нагрузки
  • Python - лучший язык программирования в мире.