Python多线程编程——threading 模块

目录

  • 前言
  • 一、进程和线程的区别
  • 二、使用threading 模块来创建多线程
    • 2-1、使用threading.Thread()方法开启线程
    • 2-2、使用join()方法来阻塞进程
    • 2-3、其他方法
  • 三、GIL锁
    • 3-1、什么是GIL?
    • 3-2、通过threading.Lock()保证线程同步
  • 总结


前言

国庆假期回来上班第一天,日常犯困。

一、进程和线程的区别

  • 进程:一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程。是操作系统资源分配的基本单元。

Python多线程编程——threading 模块_第1张图片

  • 线程进程中的一个执行单元,一个进程至少有一个线程,一个进程可以运行多个线程。是比进程更小的独立运行的基本单元,故也被成为轻量级进程。(协程是一种比线程更轻量级的存在,一个线程可以拥有多个协程。)

Python多线程编程——threading 模块_第2张图片

  • 区别
    1、根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
    2、资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
    3、包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
    4、内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的。
    5、影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮
    6、执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

二、使用threading 模块来创建多线程

2-1、使用threading.Thread()方法开启线程

# 导入threading类
import threading
import time
def thread_job():
    print('T1 start\n')
    for i in range(10):
        time.sleep(0.1)
    print('T1 finish\n')

def T2_job():
    print('T2 start\n')
    print('T2 finish\n')

def main():
	# 每个Thread对象都代表一个线程。每个线程我们可以让程序处理不同的任务,这样就是多线程编程。
	# 将需要被调用的函数传递给参数target。
	# name: 线程的名字。
	# args=(): 使用args可以传入实参。
    added_thread = threading.Thread(target=thread_job, name='T1')
    thread2 = threading.Thread(target=T2_job, name='T2')
    # 调用start方法来让线程启动。
    added_thread.start()
    thread2.start()
    print('all done\n')

if __name__ == '__main__':
    main()

输出
T1 start
T2 start
all done
T2 finish
T1 finish

Tips:默认情况下,调用start方法使得线程开始后,并不需要等待该线程执行完毕就会往下执行,所以输出看起来没那么规则。

2-2、使用join()方法来阻塞进程

# 上边的代码几个线程是同时运行的,如果让一个先运行,一个后运行,应该怎么做呢?
import threading
import time
def thread_job():
    print('T1 start\n')
    for i in range(10):
        time.sleep(0.1)
    print('T1 finish\n')

def T2_job():
    print('T2 start\n')
    print('T2 finish\n')

def main():
    added_thread = threading.Thread(target=thread_job, name='T1')
    thread2 = threading.Thread(target=T2_job, name='T2')
    added_thread.start()
    # 调用join函数可以使得该线程结束后才会接着向下执行。
    added_thread.join()
    thread2.start()
    thread2.join()
    print('all done\n')

if __name__ == '__main__':
    main()

输出
T1 start
T1 finish
T2 start
T2 finish
all done

Tips:这样看起来规则了,但是这和不使用线程直接执行函数好像没什么区别了。

2-3、其他方法

threading.currentThread() # 返回当前的线程变量。
threading.enumerate() # 返回一个包含正在运行的线程的list。。
threading.activeCount() # 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
# 也可以自定义类继承Thread,详见下方链接:Python多线程编程(一)

三、GIL锁

3-1、什么是GIL?

GIL即全局解释器锁,每个线程在执行时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说多线程并不是真正意义上的同时执行。

3-2、通过threading.Lock()保证线程同步

目的:为了协调各个线程修改同一份数据。
创建锁:lock = threading.Lock()
锁定和释放:lock.acquire()和lock.release()

参考文章:
Python多线程库threading的使用.
进程和线程的区别(超详细).
Python多线程编程(一):threading 模块 Thread 类的用法详解.

Python 多线程编程(二):threading 模块中 Lock 类的用法详解.
Python多线程之threading.Thread()基本使用.


总结

Lock类这一块后续用的上的时候再研究吧,暂时还没用到,有需要的,看倒数第二篇参考文章噢。

你可能感兴趣的:(Python,python,java,开发语言)