是否在python线程安全中修改类变量? [英] Is modifying a class variable in python threadsafe?

查看:50
本文介绍了是否在python线程安全中修改类变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读

I was reading this question (which you do not have to read because I will copy what is there... I just wanted to give show you my inspiration)...

因此,如果我有一个可以计算创建实例数的类:

So, if I have a class that counts how many instances were created:

class Foo(object):
  instance_count = 0
  def __init__(self):
    Foo.instance_count += 1

我的问题是,如果我在多个线程中创建Foo对象,instance_count是否正确?类变量可以安全地从多个线程进行修改吗?

My question is, if I create Foo objects in multiple threads, is instance_count going to be correct? Are class variables safe to modify from multiple threads?

推荐答案

即使在CPython上也不是线程安全的.试试看这个自己看看:

It's not threadsafe even on CPython. Try this to see for yourself:

import threading

class Foo(object):
    instance_count = 0

def inc_by(n):
    for i in xrange(n):
        Foo.instance_count += 1

threads = [threading.Thread(target=inc_by, args=(100000,)) for thread_nr in xrange(100)]
for thread in threads: thread.start()
for thread in threads: thread.join()

print(Foo.instance_count) # Expected 10M for threadsafe ops, I get around 5M

原因是,尽管INPLACE_ADD在GIL下是原子的,但该属性仍会加载和存储(请参见 dis.dis(Foo .__ init __)).使用锁来序列化对类变量的访问:

The reason is that while INPLACE_ADD is atomic under GIL, the attribute is still loaded and store (see dis.dis(Foo.__init__)). Use a lock to serialize the access to the class variable:

Foo.lock = threading.Lock()

def interlocked_inc(n):
    for i in xrange(n):
        with Foo.lock:
            Foo.instance_count += 1

threads = [threading.Thread(target=interlocked_inc, args=(100000,)) for thread_nr in xrange(100)]
for thread in threads: thread.start()
for thread in threads: thread.join()

print(Foo.instance_count)

这篇关于是否在python线程安全中修改类变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆