Python 类方法是线程安全的吗?
我正在处理一个在多线程环境中运行的类,看起来像这样(去除了多余的噪声):Python 类方法是线程安全的吗?,python,multithreading,python-3.x,class-method,Python,Multithreading,Python 3.x,Class Method,我正在处理一个在多线程环境中运行的类,看起来像这样(去除了多余的噪声): 我担心的是,两个线程可能同时调用apply或do\u thing,或者子类可能会尝试在其中一个函数中对cls执行一些愚蠢的操作。我可以使用staticmethod而不是classmethod,但是调用do\u thing会变得复杂得多,特别是如果子类重新实现其中一个而不是另一个。所以我的问题是:上面的类是线程安全的,还是使用这样的类方法存在潜在问题?在这方面,类方法和常规函数(以及实例方法)没有区别。两者都不是自动线程安全
我担心的是,两个线程可能同时调用
apply
或do\u thing
,或者子类可能会尝试在其中一个函数中对cls
执行一些愚蠢的操作。我可以使用staticmethod
而不是classmethod
,但是调用do\u thing
会变得复杂得多,特别是如果子类重新实现其中一个而不是另一个。所以我的问题是:上面的类是线程安全的,还是使用这样的类方法存在潜在问题?在这方面,类方法和常规函数(以及实例方法)没有区别。两者都不是自动线程安全的
如果一个或多个classmethods/methods/Function可以从不同线程同时操作数据结构,则需要添加同步保护,通常使用
threading.Lock
s.方法是否线程安全取决于该方法的功能
仅使用局部变量是线程安全的。但是,当您从不同线程更改相同的非局部变量时,它就变得不安全了
“对项执行某些操作”
似乎只修改给定的对象,该对象独立于列表中的任何其他对象,因此它应该是线程安全的
如果同一对象多次出现在列表中,则可能需要考虑使该对象线程安全。这可以通过在每个修改对象的方法中使用self.object\u scope\u lock:来实现
无论如何,您在这里所做的是使用进程而不是线程。在这种情况下,对象将被pickle并通过管道发送到另一个进程,在那里它们将被修改并发送回。与线程相反,进程不共享内存。因此,我认为在类方法中使用锁不会产生效果
另外两个答案在技术上都是正确的,因为
do_thing()
的安全性取决于函数内部发生的情况
但更准确的答案是,电话本身是安全的。换句话说,如果apply()
和do\u thing()
是a,那么您的代码是安全的。任何不安全性都是由于它们不是纯函数(例如,在执行过程中依赖或影响共享变量)
正如shx2所提到的,classmethods仅在可视的情况下“在”一个类中,用于分组。它们对类的任何实例都没有固有的附件。因此,该代码在功能上大致相当:
关于并发性的进一步说明给出了其他答案:
threading.Lock
很容易理解,但应该是您最后的选择。在幼稚的实现中,它通常比完全线性处理慢。如果您可以使用诸如线程化.Event
、队列.queue
或多处理.Pipe
之类的方法来传输信息,那么您的代码通常会更快asyncio
是python3的新热点。这是一个有点难以得到正确的,但通常是最快的方法李>
lock
的缺点从t=开始突出显示谢谢你的回答。那么简单地调用
cls.do\u thing
没有锁会很危险吗?直觉上我不这么认为,但我在多线程方面没有太多经验。
class B:
@classmethod
def apply(cls, item):
cls.do_thing(item)
@classmethod
def do_thing(cls, item)
'do something to item'
def run(self):
pool = multiprocessing.Pool()
for list_of_items in self.data_groups:
pool.map(list_of_items, self.apply)
def apply(item):
do_thing(item)
def do_thing(item)
'do something to item'
class B:
def run(self):
pool = multiprocessing.Pool()
for list_of_items in self.data_groups:
pool.map(list_of_items, apply)