☰
类变量和全局变量在多线程环境下的访问有什么区别?
2026/10/5 10:32:33 网站建设 项目流程

Python 中 类变量 vs 全局变量【多线程访问区别】

底层上两者都是共享状态,都存在线程不安全问题,但是查找路径、修改行为、隔离性有差异。 Python 多线程受 GIL 限制:同一时刻只有 1 个线程执行字节码,但不是原子操作依然会有竞态。

1. 存储位置

  • 全局变量:存放在模块的__dict__(模块字典),属于整个模块共享。
  • 类变量:存放在类对象的__dict__,所有实例共享这份类变量;实例没有重写赋值时,读的时候才去类上找。
class A: x = 0 # 类变量,在A.__dict__ g = 0 # 全局变量,当前模块 __dict__

2. 读取操作(多线程读)

只读场景下:

  • 全局变量:去模块命名空间查找
  • 类变量:A.x直接访问类字典;obj.x先查实例 dict,找不到再向上找类 dict

✅只读不加写操作:两者都安全,无竞态,只是查找链路略有差别,性能微小差距。

3. 修改操作(核心区别,多线程写)

① 全局变量

g = 0 def func(): global g g += 1

g +=1不是原子:读取 → 计算 → 写回。 多线程并发执行,会丢更新,竞态条件。 必须global声明,否则会当成局部变量。

② 类变量

class A: x = 0 def func(): A.x += 1

A.x +=1同样不是原子操作,一样会丢数据,线程不安全。

⚠️ 坑:obj.x = xxx不是修改类变量!而是给实例新增实例变量,不会改动类上的值。

a = A() a.x = 100 # 新建实例属性,A.x 不变!这是高频踩坑点

4. 作用域与隔离差异(多线程场景最关键区别)

  1. 全局变量:整个模块全部线程共享,作用域是模块级别。所有函数、所有线程都能直接读写。一旦污染,影响面极大。
  2. 类变量:共享范围仅限这个类和它的实例。
    • 不同类之间类变量互不干扰;
    • 如果你希望多组独立共享状态,可以定义多个类,天然分组隔离;
    • 全局变量做分组隔离就很麻烦,需要手动维护多个全局变量。

5. 锁使用上没有本质差别

不管是全局变量,还是类变量,并发写都需要锁保护:

from threading import Lock lock = Lock() class A: x = 0 def thread_func(): for _ in range(10000): with lock: A.x += 1

全局变量写法也是一样加锁。GIL 不会保护+=这类复合操作。

6. 对比总结表

表格

维度全局变量类变量
共享范围整个模块所有代码、线程同一个类的所有实例、类本身
存储位置模块__dict__类对象__dict__
并发读安全安全
并发写非原子,线程不安全非原子,线程不安全
修改陷阱忘记写 global,变成局部变量实例.属性=值不会修改类变量,新增实例变量
状态分组很难,容易全局污染方便,多个类天然隔离多组共享状态
生命周期模块加载创建,模块销毁释放类加载创建,类被 GC 回收销毁

7. 实践建议

  • 多线程共享状态:优先类变量封装,把共享变量 + 锁 + 操作方法封装到类内,代码更清晰、隔离好。mp.scel.cn/blog/9kLm2QpX7a.html
    mp.scel.cn/blog/Zx4Tn8Vr1B.html
    mp.scel.cn/blog/Qw7Yh3Ns5D.html
    mp.scel.cn/blog/Mc2Jv9Kp6E.html
    mp.scel.cn/blog/Rt8Bn4Xz0F.html
    mp.scel.cn/blog/Hg5Lp1Wq7G.html
    mp.scel.cn/blog/Uv3Dm6Yr2H.html
    mp.scel.cn/blog/Pa9Kc4Nt8J.html
    mp.scel.cn/blog/Se2Qx7Vb5K.html
    mp.scel.cn/blog/Fn6Wm1Zp3L.html
    mp.scel.cn/blog/Yd4Hr9Cv2M.html
    mp.scel.cn/blog/Jk7Tq3Bs8N.html
    mp.scel.cn/blog/Ol1Pm5Xw6P.html
    mp.scel.cn/blog/Bg8Nc2Vr4Q.html
    mp.scel.cn/blog/Xm5Kt7Yd1R.html
    mp.scel.cn/blog/Cv9Qp3Ln6S.html
    mp.scel.cn/blog/Zr2Wm8Hx4T.html
    mp.scel.cn/blog/Nk6Jd1Vp9U.html
    mp.scel.cn/blog/Lq4Yt7Bc2V.html
    mp.scel.cn/blog/Wp8Rm3Nx5W.html
    mp.scel.cn/blog/Td1Kv6Qs9X.html
    mp.scel.cn/blog/Hx5Pm2Zr7Y.html
    mp.scel.cn/blog/Gc9Bn4Wt1Z.html
    mp.scel.cn/blog/Vr3Lq8Jd6A.html
    mp.scel.cn/blog/Mp7Yx2Kc5B.html
    mp.scel.cn/blog/Ks4Wm9Nv3C.html
    mp.scel.cn/blog/Qn1Rt6Bp8D.html
    mp.scel.cn/blog/Dz5Jv2Xm7E.html
    mp.scel.cn/blog/Sb9Lq4Hr1F.html
    mp.scel.cn/blog/Yt3Pm8Kx6G.html
    mp.scel.cn/blog/Rc7Wn1Vd4H.html
    mp.scel.cn/blog/Bp2Qx9Lm5J.html
    mp.scel.cn/blog/Nv6Tr3Yc8K.html
    mp.scel.cn/blog/Lm1Jd7Wp2L.html
    mp.scel.cn/blog/Xq5Kv9Bn4M.html
    mp.scel.cn/blog/Ct8Rm2Hx7N.html
    mp.scel.cn/blog/Zp3Yq6Ld1P.html
    mp.scel.cn/blog/Gv9Wm4Nc5Q.html
    mp.scel.cn/blog/Hk2Jx7Rt8R.html
    mp.scel.cn/blog/Md6Pq1Bv3S.html
    mp.scel.cn/blog/Tn8Lm5Wx2T.html
    mp.scel.cn/blog/Qr4Yp9Kc7U.html
    mp.scel.cn/blog/Vx1Jv6Nd3V.html
    mp.scel.cn/blog/Kp7Wm2Ht9W.html
    mp.scel.cn/blog/Bc5Rq8Lx4X.html
    mp.scel.cn/blog/Nm9Yd3Pv1Y.html
    mp.scel.cn/blog/Lt2Kx7Bc6Z.html
    mp.scel.cn/blog/Xv8Qm4Nr5A.html
    mp.scel.cn/blog/Cp1Jd9Wt3B.html
    mp.scel.cn/blog/Zk6Lq2Yx8C.html
    mp.scel.cn/blog/Gr3Pm7Vc1D.html
    mp.scel.cn/blog/Hx9Bn5Kd4E.html
    mp.scel.cn/blog/Mv2Tq8Lm6F.html
    mp.scel.cn/blog/Tc7Yp1Rx3G.html
    mp.scel.cn/blog/Qm4Jv9Wd5H.html
    mp.scel.cn/blog/Vp8Km2Nx7J.html
    mp.scel.cn/blog/Kd1Lq6Bt9K.html
    mp.scel.cn/blog/Bx5Rm3Yc2L.html
    mp.scel.cn/blog/Nq9Pv7Hd4M.html
    mp.scel.cn/blog/Lm3Jx1Wt6N.html
    mp.scel.cn/blog/Xc8Qm5Bv2P.html
    mp.scel.cn/blog/Cv4Kd9Nr7Q.html
    mp.scel.cn/blog/Zp1Yq6Lx3R.html
    mp.scel.cn/blog/Gt7Wm2Vc9S.html
    mp.scel.cn/blog/Hk5Jv8Rd1T.html
    mp.scel.cn/blog/Mx9Pq3Bn6U.html
    mp.scel.cn/blog/Tm2Ld7Wv4V.html
    mp.scel.cn/blog/Qc6Yp1Kx8W.html
    mp.scel.cn/blog/Vr3Jm9Nt5X.html
    mp.scel.cn/blog/Kp8Qv4Bd2Y.html
    mp.scel.cn/blog/Bm1Lx6Wc7Z.html
    mp.scel.cn/blog/Nv5Rd9Yp3A.html
    mp.scel.cn/blog/Lq2Km7Jx8B.html
    mp.scel.cn/blog/Xt9Pm4Vc1C.html
    mp.scel.cn/blog/Cd3Qv8Bn6D.html
    mp.scel.cn/blog/Zx7Lp2Yr5E.html
    mp.scel.cn/blog/Gm1Jd6Wv9F.html
    mp.scel.cn/blog/Hv4Kq9Nx2G.html
    mp.scel.cn/blog/Mp8Rm3Bc7H.html
    mp.scel.cn/blog/Tq1Yv5Ld4J.html
    mp.scel.cn/blog/Qx6Jm2Wt9K.html
    mp.scel.cn/blog/Vc3Pq7Rn1L.html
    mp.scel.cn/blog/Km9Ld4Bv6M.html
    mp.scel.cn/blog/Bp2Xv8Yc3N.html
    mp.scel.cn/blog/Nr5Qm1Jx7P.html
    mp.scel.cn/blog/Lv8Kd3Wt2Q.html
    mp.scel.cn/blog/Xm4Pq9Bc6R.html
    mp.scel.cn/blog/Ct1Rv7Lx5S.html
    mp.scel.cn/blog/Zp8Jm2Yd4T.html
    mp.scel.cn/blog/Gq3Kv6Nx9U.html
    mp.scel.cn/blog/Hm7Ld1Wc5V.html
    mp.scel.cn/blog/Mv4Pq8Bt2W.html
    mp.scel.cn/blog/Tr9Ym3Jx6X.html
    mp.scel.cn/blog/Qc2Kv7Ld1Y.html
    mp.scel.cn/blog/Vp6Rm4Nc8Z.html
    mp.scel.cn/blog/Kx1Jd9Wv3A.html
    mp.scel.cn/blog/Bm5Qq2Yt7B.html
    mp.scel.cn/blog/Nc8Lm4Hx1C.html
    mp.scel.cn/blog/Lv3Pq9Rd6D.html
    mp.scel.cn/blog/Xt7Km2Bc5E.html
  • 尽量少用全局变量,全局状态容易被任意函数意外修改,调试困难。
  • 无论用哪一种,只要存在并发写,都必须加锁。

如果你想,我可以写一段完整可运行代码,演示类变量多线程丢值和全局变量多线程丢值的对比。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询