python多线程重入陷阱

多线程使用容易出现重入问题,有时这种重入不易发觉,我们一起看下面这个例子:

import threading
import time


class A:
    def func(self, num):
        self.num = num
        time.sleep(5)
        return self.num


class TestThread(threading.Thread):
    def __init__(self, thread_id, func):
        threading.Thread.__init__(self, name='test')
        self.func = func
        self.thread_id = thread_id

    def run(self):
        num = self.func(self.thread_id)
        print("线程{thread_id}:{num}".format(thread_id=self.thread_id, num=num))


a = A()
th_list = list()
for i in range(5):
    th = TestThread(i, a.func)
    th_list.append(th)

for i in range(5):
    th_list[i].start()

for i in range(5):
    th_list[i].join()

上面这个例子中,多线程类调用了一个类A的成员函数func,而这个func函数会设置A的成员变量num,将线程id传递给func,并且打印返回值,最终的结果如下,发现所有线程中打印出来的数值都是4。

线程1:4
线程0:4
线程2:4
线程3:4
线程4:4

这个的根本原因是:A只有一个实例,虽然传递给各个线程的只是一个成员函数,但这个成员函数可以设置类的成员变量, 这个成员变量因此会被多个线程操纵,造成修改

所以在多线程使用中,谨慎传递类成员函数,因为可以造成变量被覆盖等问题,应当给每个线程实例化自己的对象,调用各个实例自己的成员函数,这样就不会互相干扰。

如下面代码的这种实现方式,就可以解决这个问题:

import threading
import time


class A:
    def func(self, num):
        self.num = num
        time.sleep(5)
        return self.num


class TestThread(threading.Thread):
    def __init__(self, thread_id, Class):
        threading.Thread.__init__(self, name='test')
        a = Class()
        self.func = a.func
        self.thread_id = thread_id

    def run(self):
        num = self.func(self.thread_id)
        print("线程{thread_id}:{num}".format(thread_id=self.thread_id, num=num))


th_list = list()
for i in range(5):
    th = TestThread(i, A)
    th_list.append(th)

for i in range(5):
    th_list[i].start()

for i in range(5):
    th_list[i].join()

线程0:0
线程1:1
线程3:3
线程2:2
线程4:4
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 8,076评论 2 9
  • 写在前面的话 代码中的# > 表示的是输出结果 输入 使用input()函数 用法 注意input函数输出的均是字...
    FlyingLittlePG阅读 8,224评论 0 9
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,909评论 1 32
  • 昨日阅读1小时,总计258小时,第244日。 读吕思勉《两晋南北朝史》至54% 甚哉,积习之不易变也!荒淫、猜忌,...
    龙套哥萨克海龙阅读 4,108评论 0 0
  • 幽寺访禅客,烦襟此一开。 山空有猿鹤,地僻无尘埃。 ​烹茶绿云起,鼓扇清风来。 览景不归去,暮烟生古台。 如此美好...
    皓妈童书分享会阅读 5,464评论 0 3

友情链接更多精彩内容