关于 Python 线程详述

线程是进程内的独立的运行线路,是操作系统能够进行运算调度的最小单位,同时也是处理器调度的最小单位。线程被包含在进程之内,是进程中实际运作单位。

一个线程指的是进程中的一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

Python中如何使用多线程?

首先要import threading

线程有两种调用方式,第一种是直接调用

import threading
import time
# 直接调用

def run(n):
    print("task {0} {1}".format(n,threading.current_thread()))
    time.sleep(2)

if __name__ == "__main__":

t1 = threading.Thread(target=run,args=("t1",)) # 参数括号内的逗号不能省略
    t2 = threading.Thread(target=run,args=("t2",)) # 生成一个线程对象

t1.start() # 启动线程
    t2.start()

# 现在同时启动50个线程
    start = time.time()
    for i in range(50):
        t= threading.Thread(target=run,args=("t{0}".format(i),))
        t.start()
    end = time.time()
    cost = end - start
    print("cost time:",cost)

第二种是继承式

import threading
import time
'''继承式调用'''

class MyThread(threading.Thread):
    def __init__(self,n):
        super(MyThread,self).__init__()
        self.n = n

def run(self):
        print("running task{0}  {1}".format(self.n,threading.current_thread()))
        time.sleep(1)

if __name__ == "__main__":

start = time.time()
    obj = []

for i in range(50):
        t= MyThread("t{0}".format(i))
        t.start()

end = time.time()
    cost = end - start
    print("cost time:",cost)

使用多线程对比函数调用,得出结论是:线程是并发执行的(同时执行),而函数调用只能是顺序执行,多线程执行大大提高了运行效率。

但是以上两个程序在运行的时候发现了一个共同的问题:拿继承式的代码来说,理论上50个线程执行完需要经过一秒多才会执行完毕,退出程序,但是实际情况却是开启50个线程之后立马就退出程序,执行时间不足0.01s。为什么呢?

  答案是多线程。当前运行的线程是主线程,主线程启动了50个子线程,启动完毕后继续做自己的事情,每个线程之间互不干扰,并行运行。因此无法用此方式测定50个程序到底运行了多久。

  主线程运行完毕即退出程序,如果不特殊处理,它不会等待子线程处理完毕。所以我们如果想要等待子线程的运行结果,需要加上join()语句。

import threading
import time
'''继承式调用'''

class MyThread(threading.Thread):
    def __init__(self,n):
        super(MyThread,self).__init__()
        self.n = n

def run(self):
        print("running task{0}  {1}".format(self.n,threading.current_thread()))
        time.sleep(1)

if __name__ == "__main__":

start = time.time()
    obj = []

for i in range(50):
        t= MyThread("t{0}".format(i))
        t.start()
        obj.append(t) # 为了不阻塞后面线程的启动,现将其加入列表

for j in obj:
        j.join()
    print(threading.current_thread())  # 证明主线程
    end = time.time()
    cost = end - start
    print("cost time:",cost)

当线程被启动后,如果调用join()方法,则会在此线程执行完之前程序不往下走,也就是阻塞当前程序,使程序变为串行执行,这当然不是我们愿意看到的。在此程序中,我们希望它并发执行的同时,满足主线程等待所有子线程执行完毕后再结束这个条件。只需要在开启所有线程之后,一一地join()即可。

线程锁

在线程锁之间讲一下GIL全局性解释器锁。

首先要明白GIL并不是Python的特性,它是在实现Python解释器(CPython)时引入的一个概念。简单来说,GIL锁的存在使得:无论你开启多少个线程,无论你的CPU有多少核,在执行程序的时候同一时间只会占用一个核。所以,你以为的同时占用多核只是假象。再说一遍,这不是Python的特性,这只是CPyhton解释器的特性,其他类型的解释器如JPyhon,pypy等没有这个特性。之所以我们在使用Python多线程时没有感觉是单线程是因为上下文的切换。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d543f07ad69e5d46f1b16ed0b5f37e1f.html