【python3基础学习】【第9周】进程与线程

本文深入介绍了Python中的线程和进程概念,详细讲解了多线程的实现方式,包括函数式和类实现。同时,讨论了线程的等待、守护、GIL全局解释锁、互斥锁、递归锁以及信号量等同步机制。通过实例展示了如何控制线程执行和管理资源,帮助读者理解Python多线程编程的关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念

  • 线程:
  1. 操作系统最小的调度单位,是一串指令的集合;
  • 进程:
  1. 以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等,对各种资源管理的集合就可以称为进程,例如:qq就是一个进程;
  2. 要操作cpu,必须要先创建一个线程;
  3. 所有在同一个进程里的线程是共享同一块内存空间的;
  • 注意:
  1. 线程共享内存空间,进程的内存是独立的;
  2. 同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现;
  3. 创建线程很简单,创建新进程需要对其父进程进行一次克隆;
  4. 一个线程可以控制和操作同一个进程里其他线程,但是进程只能操作子进程;

二、多线程小知识点

1、多线程基本实现

  • 方法1:
import threading
import time


def run(name):
    print("task ", name)
    time.sleep(5)


if __name__ == '__main__':
    t1 = threading.Thread(target=run, args=("t1", ))
    t2 = threading.Thread(target=run, args=("t2", ))

    t1.start()
    t2.start()
  • 方法2:类实现
import threading
import time


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

    def run(self):
        print("task ", self.name)
        time.sleep(5)


if __name__ == '__main__':
    t1 = MyThread("t1")
    t2 = MyThread("t2")

    t1.start()
    t2.start()

2、等待线程停止: t.join()

  • 计算多线程执行耗时:
import threading
import time


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

    def run(self):
        print("task ", self.name)
        time.sleep(5)


if __name__ == '__main__':
    # 记录程序运行开始时间
    start_time = time.time()
    # 用于保存多线程实例, 用于判断所有线程执行完成
    threads_list = []

    # 循环启动多线程
    for i in range(50):
        t = MyThread(i)
        t.start()
        threads_list.append(t)

    # join等待所有线程执行完成;
    for t in threads_list:
        t.join()
    
    # 计算多线程执行耗时
    end_time = time.time()
    cost_time = end_time - start_time
    print("多线程运行, 共计耗时: %s秒" % cost_time)

3、守护线程:setDaemon,主线程结束时,守护线程都会强制结束

import threading
import time


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

    def run(self):
        print("task ", self.name)
        time.sleep(5)


if __name__ == '__main__':
    # 记录程序运行开始时间
    start_time = time.time()

    # 循环启动多线程
    for i in range(50):
        t = MyThread(i)
        t.setDaemon(True)
        t.start()

    # 计算多线程执行耗时
    end_time = time.time()
    cost_time = end_time - start_time
    print("多线程运行, 共计耗时: %s秒" % cost_time)

4、CPython GIL介绍:全局解释锁

  • 注意点:
    机智的同学可能会问到这个问题,就是既然你之前说过了,Python已经有一个GIL来保证同一时间只能有一个线程来执行了,为什么这里还需要lock? 注意啦,这里的lock是用户级的lock,跟那个GIL没关系 ,具体我们通过下图来看一下+配合我现场讲给大家,就明白了。
    在这里插入图片描述

5、线程锁(互斥锁Mutex):threading.Lock()

import time
import threading
 
def addNum():
    global num #在每个线程中都获取这个全局变量
    print('--get num:',num )
    time.sleep(1)
    lock.acquire() #修改数据前加锁
    num  -=1 #对此公共变量进行-1操作
    lock.release() #修改后释放
 
num = 100  #设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
 
for t in thread_list: #等待所有线程执行完毕
    t.join()
 
print('final num:', num )

6、python中lock和rlock(递归锁)的区别

  • 在threading模块中,定义两种类型的琐:threading.Lock和threading.RLock。它们之间有一点细微的区别,通过比较下面两段代码来说明。
  • 这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
import threading  
lock = threading.Lock() #Lock对象  
lock.acquire()  
lock.acquire()  #产生了死琐。  
lock.release()  
lock.release()  
import threading  
rLock = threading.RLock()  #RLock对象  
rLock.acquire()  
rLock.acquire() #在同一线程内,程序不会堵塞。  
rLock.release()  
rLock.release()  

7、Semaphore(信号量)

  • 互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time
 
def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" %n)
    semaphore.release()
 
if __name__ == '__main__':
 
    num= 0
    semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()
 
while threading.active_count() != 1:
    pass #print threading.active_count()
else:
    print('----all threads done---')
    print(num)

2.

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值