python中使用通用函数的多线程

时间:2018-04-30 12:34:20

标签: python

我使用了多线程执行独立代码(它们之间没有任何公共代码),但这一次,我必须使用一个在每个线程中调用的公共函数。所以,如果能起作用我会有点困惑。例如,

thread1:
 #do something
 input_list = [5,6,7,8]
 output_list = common_function(input_list)
 print output_list

thread2:
 #do something
 input_list = [1,2,3,4]
 output_list = common_function(input_list)
 print output_list

上述代码是否会成为一个问题,也许是因为竞争条件?或者python会自动处理这个? common_function(input_data)根据提供的输入返回一个列表,然后显示该列表。对于一个小数据集,它可以工作,但我的问题是,如果input_list变得庞大,是否会导致代码出现问题?

3 个答案:

答案 0 :(得分:1)

如果common_function是一个没有任何副作用的函数,那就是保存。换句话说,如果common_function仅适用于input_list并且不使用任何其他内容(没有共享数据,没有服务),则可以并行调用该函数。只要不与任何其他线程共享,输入数据的大小就无关紧要。

答案 1 :(得分:0)

如果您使用的是threading软件包,则可以在写入之前使用semaphore锁定变量。就像这里的例子:

import threading

lock = threading.BoundedSemaphore()

def function():
    lock.acquire()  # Lock the Variable
    # Write to your List
    lock.release()  # Release the Variable

因此,acquirerelease之间的所有内容都是为线程保存

答案 2 :(得分:0)

正如@lutz所写,如果common_function的两个实例之间没有共享数据,则不存在竞争条件的危险。这就是引用透明度的含义,通常所有编程语言都认为这些函数应该是线程安全的。有时,您需要编写和使用改变某些全局状态的函数。在这种情况下,现代格言是使用事件驱动编程 - 这意味着不在线程之间直接通信,而是通过一些线程安全排队系统进行通信。在python中,我是queue module的忠实粉丝。另一个好的队列模块是multiprocessing.queue,其中一个很好的例子是here。我也在这里粘贴代码。

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'hello'])

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print(q.get())    # prints "[42, None, 'hello']"
    p.join()

最后,如果你对某些功能没有信心(可能它是一个很大的功能而且你不了解它的螺母和螺栓),我建议你使用模糊方法。在这里定义一个简单的函数

FUZZ = True
def fuzz():
    """
    fuzzing is a technique to make the race condition errors more visible
    """
    if FUZZ:
        time.sleep(random.random())

然后将此函数放在代码中的随机位置。这应该放大代码中存在的任何竞争条件。这当然不是一种保证方法,所以如果你的函数在生产应用程序中被调用了数百万次,那么更好的策略就是将函数分解为更小的易消化部分。观看Raymond Hettinger在his famous talk on python threading发表关于并发代码的演讲。您可以获得他正在谈论的代码here