什么是使用python多线程访问共享数据的最佳实践

时间:2017-10-27 09:30:07

标签: python multithreading

在python多线程中,有一些原子类型可以访问 由多个线程没有保护(列表,字典等)。还有一些类型需要锁定保护。

我的问题是:

  1. 我在哪里可以找到列出所有原子类型的官方文档,我可以谷歌一些答案,但它们不是"官方"并且过时了。

  2. 有些书建议我们应该用锁保护所有共享数据,因为原子类型可能因为非原子,我们不应该依赖它。它是否正确? 因为锁肯定有开销,即使有大程序,这个开销是否可以忽略不计?

2 个答案:

答案 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的答案。