Python学习总结四:线程及锁的基本介绍

本人录制技术视频地址:https://edu.csdn.net/lecturer/1899 欢迎观看。
线程的概念,不管在哪种语言中,大家都应该接触了不少,我这里就不再说明,这一节就用几个小例子说明一下,线程和锁在Python中的使用。

一、直接使用Thread构造方法

开辟四个线程异步执行任务,其中前三个线程执行的都是单独的一个网络请求,而最后一个线程执行了两个网络请求。

import threading
import requests

def display_info(code):
    url = 'http://hq.sinajs.cn/list=' + code
    response = requests.get(url).text
    print(response)

def single_task(codes):
    for code in codes:
        code = code.strip()
        display_info(code) 

def exec_task(tasks):
    threads = []
    for t in tasks:
        threads.append(threading.Thread(target = single_task, args=(t, )))
    for t in threads:
        t.start()
    for t in threads:
        t.join()

def main():
    stocks = ['sh600001', 'sh600002', 'sh600003', 'sh600004', 'sh600005']
    step = int(len(stocks) / 4)
    t1 = stocks[0: step]
    t2 = stocks[step: step * 2]
    t3 = stocks[step * 2: step * 3]
    t4 = stocks[step * 3:]

    exec_task([t1, t2, t3, t4])

if __name__ == '__main__':
    main()

代码中,需要说明的是下面这句代码:
threads.append(threading.Thread(target = single_task, args=(t, )))
1. 调用线程的构造方法,需要传入两个参数。第一个是执行线程的方法,本例中是single_task, 另一个就是线程调用方法传入的参数args
2. 注意args传入参数的格式是一个元祖,并且第二个参数是空。这是由于语法格式决定的,这个只能传入元祖,如果我们将args传入的值直接写成args=t, 则会报下面的错误。
TypeError: single_task() takes 1 positional argument but 2 were given

二、自定义Thread类

开辟三个线程,每个线程打印五次。


import time
import threading

class MyThread(threading.Thread):
    def run(self):
        name = threading.current_thread().name
        for i in range(5):
            print('sub thread_{}, @number:{}'.format(name, i))
            time.sleep(1)

def main():
    name = threading.current_thread().name
    print('Start main threading %s' % name)
    threads = [MyThread() for i in range(3)]
    for t in threads:
        t.start()

    # join (上述的例子中,主线程结束了,子线程还在运行。如果需要主线程等待子线程执行完毕再退出,可是使用线程的join方法)
    for t in threads:
        t.join()

    print('End main threading')

if __name__ == '__main__':
    main()

代码中有两点需要说明:
1. 主线程中的线程名称是0,其他的线程名称不是0.
2. 创建三个线程使用了快速创建数组的方式 threads = [MyThread() for i in range(3)]

三、锁的使用说明

使用多线程,大家都会遇到线程资源竞争的问题,解决方案就是对公用资源加锁。当有一个线程在访问共有资源的时候,其他线程排队等待。Python加锁的大致代码如下:


import time
import threading

lock = threading.Lock()

balance = 0
def change_it(n):
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(num):
    for i in range(1000):
        lock.acquire()
        try:
            change_it(num)
        finally:
            lock.release()

thread1 = threading.Thread(target = run_thread, args=(5, ))
thread2 = threading.Thread(target = run_thread, args=(8, ))
thread1.start()
thread2.start()
thread1.join()
thread2.join()

print('balance value is %d' % balance)

代码中有两点需要说明:
1. 加锁使用的是lock.acquire(), 解锁使用的是lock.release()
2. 代码使用了try finally语法,原因是因为如果change_it(num)这个方法执行出现了异常,那么锁就解不掉了。

猜你喜欢

转载自blog.csdn.net/sinat_27706697/article/details/79125021