在python多线程中,有一些原子类型可以访问 由多个线程没有保护(列表,字典等)。还有一些类型需要锁定保护。
我的问题是:
我在哪里可以找到列出所有原子类型的官方文档,我可以谷歌一些答案,但它们不是"官方"并且过时了。
有些书建议我们应该用锁保护所有共享数据,因为原子类型可能因为非原子,我们不应该依赖它。它是否正确? 因为锁肯定有开销,即使有大程序,这个开销是否可以忽略不计?
答案 0 :(得分:1)
锁定用于使操作成为原子。这意味着只有一个线程可以访问某些资源。 使用多个锁会导致您的应用程序失去线程的好处,因为只有一个线程可以访问该资源。
如果你考虑一下,那就没有多大意义了。它会使你的程序变慢,因为python需要管理和线程之间的上下文切换。
使用线程时,您应该尽可能多地寻找最小化锁的数量。尽可能尝试使用局部变量。使您的函数执行某些操作,并返回值而不是更新现有值。 然后,您可以创建一个队列并收集结果。
除了锁,还有信号量。这些基本上都是锁,有限数量的线程可以使用它:
信号量管理一个内部计数器,该计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不会低于零;当acquire()发现它为零时,它会阻塞,等待其他线程调用release()。
Python为threading module提供了很好的文档。
以下是使用单线程与3线程测试的虚拟函数的一个小示例。注意影响锁对运行时间的影响:
线程(无锁)持续时间:1.0949997901
线程(带锁)持续时间:3.1289999485
单线程持续时间:3.09899997711
def work():
x = 0
for i in range(100):
x += i
lock.acquire()
print 'acquried lock, do some calculations'
time.sleep(1)
print x
lock.release()
print 'lock released'
答案 1 :(得分:0)
我认为你正在寻找这个link。
从上面链接:
作用于共享内存的操作如果在a中完成则是原子操作 相对于其他线程的单步。当一个原子商店是 在共享变量上执行,没有其他线程可以观察到 修改半完成。当对a执行原子加载时 共享变量,它读取单个出现的整个值 这一刻。非原子载荷和商店不会产生这些 保证。
列表上的任何操作都不是原子操作,因此需要特别注意使用Lock,Event,Condition或Semaphores等使其线程安全。
例如,您可以查看解释how list are thread safe的答案。