美文网首页
[CP_04] Python进程|多进程|线程|多线程|线程锁

[CP_04] Python进程|多进程|线程|多线程|线程锁

作者: Fighting_001 | 来源:发表于2019-03-18 23:41 被阅读0次

目录结构

一、进程
二、线程
    1. 多线程实现
    2. 主线程和子线程
    3. 线程锁(互斥锁)
    4. 多线程案例:多个窗口并行售票
    5. 全局解释器锁(GIL)
三、多进程

一、进程

进程:描述程序文件从运行开始到结束的过程

进程有三个状态:就绪、运行、阻塞

  • 就绪态:获取了除CPU以外的所有资源,只要处理器分配资源就可马上执行。
  • 运行态:获得了处理器分配的资源,程序开始执行。
  • 阻塞态:当程序条件不够时,需要等待条件满足时侯才能执行。如等待i/o操作时,此刻的状态就叫阻塞态。

二、线程

  • 线程:一个进程可以包含多个线程(≥1个线程),进程作为分配资源的基本单位;线程作为进程下更小的划分单位,需要依赖于进程而执行,线程可利用进程所拥有的资源
  • 多线程:一个应用程序中有多个执行部分可同时执行,同一时间完成多项任务,以提高资源使用效率。如:QQ软件可同时实现播放音效、消息发送等功能

1. 多线程实现

Python标准库提供的2个模块:_thread(低级模块)、threading(高级模块,已对_thread进行封装)
启动一个线程:创建线程+执行线程。把一个函数传入并创建Thread实例,然后调用start()开始执行

案例:多个线程并行执行;同时(同一个时间段)执行多个线程

PS:多线程执行时的"同时"非同一时刻,而是同一时间段内

multiThread.py

import threading
import time

# 定义执行线程的方法
def run(name):
    print(name,"线程执行")
    time.sleep(3)

# 创建2个线程
# target传入调用的方法,args传入对应方法的参数(每个参数后需要加上',')
t1=threading.Thread(target=run,args=("t001",))
t2=threading.Thread(target=run,args=("t002",))
t3=threading.Thread(target=run,args=("t003",))

print("---执行开始---\n")

# 启动线程(执行)
t1.start()
t2.start()
t3.start()

print("\n---执行完毕---")

执行结果:

以上,3个线程并行执行,花费的总时间是3.4s(包含3s的延迟时间),实际执行花费0.4s

2. 主线程和子线程

  • 主线程:程序执行时,程序本身就是一个线程,作为主线程
  • 子线程:程序中所手动创建的线程,作为子线程

PS:
①程序无设置的情况下,主线程不会等待子线程执行完毕才执行,而是直接执行
②若程序中采用线程对象调用join()方法,则可设置先执行完成子线程,然后才执行主线程

以上multiThread.py程序中的print("\n---执行完毕---")属于主线程中的一部分,t1.start()属于子线程,子线程开始执行后,未执行完成3s等待,主线程就会先打印 "---执行完毕---",然后3s后程序才会真正执行完成

以下采用线程对象调用join()方法,实现先执行完成子线程(包括等待3s),然后才会执行主线程中的print("\n---执行完毕---")
在代码中新增:

# 等待子线程执行完成之后再执行主线程内容
t1.join()
t2.join()
t3.join()

3. 线程锁(互斥锁)

线程锁:解决某个线程执行到一半又去执行另一个线程,导致的多线程执行产生错乱。具体表现为:多线程执行过程中,将每个子线程执行的代码作为一个完整的单元进行锁定,执行某个单元未完成时不跳出执行,执行完成一个完整的单元即进行解锁释放。

代码实现:
threadLock.py

import threading

# 创建一个线程锁
lock=threading.Lock()

num=10  # 当前需要执行的线程数

def run(name):
    lock.acquire()  # 设置锁
    global num  # 设置num为全局变量
    num=num-1
    print("线程",name,"执行了,目前剩余执行的线程数:",num)
    lock.release()  # 释放锁

# 创建并启动线程
for i in range(10):
    t=threading.Thread(target=run,args=(i+1,))
    t.start()

执行结果:

若未加线程锁,则会出现执行和统计错乱,如下:

4. 多线程案例:多个窗口并行售票

案例:利用Python多线程机制,模拟多窗口(对应多个线程)并行进行售票,所有票售完为止

sale.py

import threading

lock=threading.Lock()
num=100

# 定义售票方法
def sale(name):
    lock.acquire()
    global num
    if num>=1:
        num=num-1
        print(name,"卖出一张票,当前余票数:",num)
    lock.release()

# 售票窗口(与多线程中线程数目对应)
while True:
    if num>=1:
        t1=threading.Thread(target=sale,args=("A窗口",))
        t2=threading.Thread(target=sale,args=("B窗口",))
        t3=threading.Thread(target=sale,args=("C窗口",))
        t4=threading.Thread(target=sale,args=("D窗口",))
        t5=threading.Thread(target=sale,args=("E窗口",))
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        t5.start()
    else:
        print("票已售罄!")
        break

执行结果:

5. 全局解释器锁(GIL)

GIL(Global Interpreter Lock)使得在Python程序中,不管CPU核心数有多少,同一时间点只能执行一个线程。缺点:本意是为了实现数据安全,但CPU资源的浪费,发挥不了多核的优势,程序执行效率低,弊大于利

三、多进程

使用多进程解决GIL所造成的问题,多进程可实现同一时间点多个任务并行

multiProcess.py

from multiprocessing import Process
import time

def run(name):
    print(name,"进程执行")
    time.sleep(3)

if __name__=='__main__':    # Windows系统中需要写入到main方法中
    # 创建进程
    p1=Process(target=run,args=("pr1",))
    p2=Process(target=run,args=("pr2",))
    p3=Process(target=run,args=("pr3",))
    p4=Process(target=run,args=("pr4",))
    p5=Process(target=run,args=("pr5",))

    # 启动线程
    p1.start()
    p2.start()
    p3.start()
    p4.start()
    p5.start()

相关文章

网友评论

      本文标题:[CP_04] Python进程|多进程|线程|多线程|线程锁

      本文链接:https://www.haomeiwen.com/subject/mddumqtx.html