问题描述
我正在阅读这个问题,它询问生成器是否是线程安全的,还有一个回答说:
另一个答案显示,您可以使用锁来确保一次只有一个线程使用生成器. /p>
我是多线程新手.谁能设计一个例子来说明当您使用无锁发生器时到底发生了什么?
例如,如果我这样做,似乎没有任何问题:
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()
运行此示例.
您将看到10,000个数字将在线程之间共享".在两个线程中都不会看到10000个数字.
实际上最有可能一个线程看到所有数字.
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
I'm reading this question which asks if generators are thread-safe, and one answer said:
Another answer shows that you can use a lock to ensure that only one thread uses the generator at a time.
I'm new to multithreading. Can anyone devise an example to show what exactly happens when you use the generator without lock?
For example, it doesn't seem to have any problems if I do this:
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()
Run this example.
You'll see that the 10 000 numbers will be "shared" across threads. You won't see the 10 000 numbers in both threads.
It's actually most likely that one thread will see all the numbers.
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
Actually, if it happens that Python switches threads during execution (just use a higher value than 10000, e.g. 10000000), you'll get an exception:
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
这篇关于多线程:为什么生成器不是线程安全的?在线程之间共享时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!