在python中使用公共函数进行多线程处理

2024-04-28 03:24:22 发布

您现在位置: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自动处理这个问题?公共_函数(输入_数据)根据提供的输入返回一个列表,然后显示该列表。对于一个小的数据集,它是有效的,但我的问题是,如果输入列表变得巨大,它会导致代码中出现问题吗


Tags: 数据函数代码列表inputoutputfunctioncommon
3条回答

如果common_function是一个没有任何副作用的函数,这就是save。换句话说,如果common_function只在input_list上工作,而不使用其他任何东西(没有共享数据,没有服务),则可以并行调用该函数。只要不与任何其他线程共享,输入数据的大小就无关紧要

正如@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

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

import threading

lock = threading.BoundedSemaphore()

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

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

相关问题 更多 >