2022年 11月 13日

python爬虫-23-python多线程详解(2)继承类,以及多线程锁

图片

1、python之多线程threading封装

==========================

为了让线程代码更好的封装。可以使用threading模块下的Thread类,继承自这个类,然后实现run方法,线程就会自动运行run方法中的代码。

我们可以将上一篇的代码进行封装,封装之后的代码:

import threading
from datetime import datetime
import time


class Eating(threading.Thread):
    def run(self):
        for i in range(3):
            print("正在吃第{}顿饭\n".format(i))
            time.sleep(1)


class Studying(threading.Thread):
    def run(self):
        for i in range(3):
            print("运维家{}颗心\n".format(i))
            time.sleep(1)


def Total():
    Start = datetime.now()
    T1 = Eating()
    T2 = Studying()
    T1.start()
    T2.start()
    T1.join()
    T2.join()
    Stop = datetime.now()
    Total_time = Stop - Start
    print("该代码运行时间为:{}".format(Total_time))


if __name__ == '__main__':
    Total()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

运行结果如下:

正在吃第0顿饭

运维家0颗心

运维家1颗心
正在吃第1顿饭


运维家2颗心
正在吃第2顿饭


该代码运行时间为:0:00:03.014794

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们可以看到,通过重写pythonthreading.Threadrun方法,我们也成功的实现了多线程,且更加优雅。

2、threading之锁机制

我们想一个问题哈,当你这个代码中有一个全局变量A 同时被两个线程进行调用的时候,我们该如何保证这个变量保持一个先后顺序来被调用呢,因为当你启动了两个线程之后,我们是无法控制线程的运行顺序的,那么在这样子的前提下,是不是就存在那么一种数据错乱的可能性呢。

例如,当全局变量A被线程C调用的时候,线程D也来调用全局变量A 了,那么此时是不是全局变量A就有可能发生变化,在这种情况下,当线程C再次来调用全局变量A的时候,数据是不是就不准了呀,我们来简单看个例子吧:

import threading

A = 0


def Thread_C():
    global A
    for c in range(1000000):
        A += 1
    print(A)


def Thread_D():
    global A
    for d in range(1000000):
        A += 1
    print(A)


def main():
    T1 = threading.Thread(target=Thread_C)
    T2 = threading.Thread(target=Thread_D)
    T1.start()
    T2.start()
    T1.join()
    T2.join()


if __name__ == '__main__':
    main()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

运行之后输出结果如下:

1302844
1717930

  • 1
  • 2
  • 3

可以看到两个输出内容,一个是1302844,另一个是1717930,当我们再次运行的时候,这个结果会再次发生变化;

但是正常逻辑来说呢,他应该输出一个1000000和一个2000000,对吧,其实这种情况在数量较少的情况下是有可能不会有问题的,因为在你第二个线程还没有启动的时候,第一个线程就已经执行完了,所以数量少的情况下,就有可能没问题。

那么这个情况,就是没有给变量上锁,导致多个线程同时调用一个可变的全局变量,导致的该问题;

python也给我们提供了解决方法,就是当有这种情况发生的时候,我们通过给某个线程访问某个变量的时候上锁,确保该线程在调用某个变量的时候,其他线程无法访问进行,让其处于等待状态,直到该线程处理完毕,将锁释放,该变量才会被其他线程调用,那么这种情况就不会有上面的情况出现了,我们看下如何实现吧。

方法:

threading.Lock()

  • 1
  • 2

代码:

剩余内容请转至VX公众号 “运维家” ,回复 “184” 查看。

—— “运维家” ,回复 “184” ——
—— “运维家” ,回复 “184” ——
—— “运维家” ,回复 “184” ——

系统运维工程师,运维工程师技能要求,成都运维工程师驻场开发收费标准,t3网络运维工程师,运维工程师社会需求,运维工程师修炼手册;
oppo高级运维工程师社招,运维工程师员招聘要求,中级运维工程师技术水平,大数据运维工程师月薪多少,运维工程师的个人发展计划,应届生面试运维工程师穿着;
系统运维运维工程师,中国移动网络运维工程师笔试,徐州市苏宠集团运维工程师待遇,云南运维工程师培训班;
监控系统运维工程师,高铁运维工程师是正式工 吗,郑卅软件运维工程师招聘,运维助理工程师好不好。