Python 线程与进程 1

本文介绍了Python中线程和进程的创建,强调了GIL锁对多线程的影响以及多进程的使用场景。提到了线程安全的概念,通过示例展示了如何使用锁(Lock和RLock)来保证数据同步。此外,还讨论了线程池的使用,以优化大量线程的管理,并通过单例模式展示了线程安全的类设计。

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

线程方面自己写东西老出BUG
所以复习下

线程的创建

Def fuc(a1,a2,a3):
Print(‘??’)
T = threading.Thread(traget = fuc,args=(11,22,33))
让线程开始工作
T.start()

进程的创建

T = multiprocessing.Process(target = 函数名,args = (name,url))
T.start()

有一个小细节就是在编写多进程的时候要把多进程创建写到

if __name__ == ‘__main__’:

里面不然会报错
因为windows是spawn,linux是fork,Mac是fork和spawn(python 3.8 默认设置spawn)

multiprocessing.set_start_method(‘fork’)

提前设置就不用写if name == ‘main’:
但是多进程的开销比多线程要大是毋庸置疑的

GIL锁

GIL锁是全局解释器锁,是CPython解释器特有一个玩意儿,让一个进程中同一个时刻只能有一个线程可以被CPU调用那么想利用计算机的多核优势,让CPU同时处理一些任务,适合用多进程开发(即使资源开销大)
从上古时期就流传过这两句话
计算密集型,用多进程
IO密集型,用多线程

多线程开发 多线程的细节

线程的常见方法

T.start()当前线程准备就绪(等待CPU调度,具体时间由CPU决定)
T.join()等待当前线程的任务完成后再继续执行下去
T.setDaemon(True) 设置为守护线程,主线程执行完毕后,子线程也自动关闭
T.setDaemon(False) 设置为非守护线程,主线程等待子线程,子线程执行完毕后,主线程才结束
setDaemon有些高版本python不适应了
在这里插入图片描述
在这里插入图片描述

使用类方法创建线程

在这里插入图片描述

线程安全

一个线程中可以有多个线程,且线程中的资源会被共享。那么当一个线程加一个锁让别的线程访问不了就可以了
创建锁
Lock_object = threading.RLock()
加申请锁
Lock_object.acquire()
这里的申请锁在两个线程的里都要写后,一个线程加锁后另个线程不能访问锁下面的内容要一直等待另一方解锁
解锁
Lock_object.release()

mport threading
num = 0
lock_object = threading.RLock()
def task():
    global num
    lock_object.acquire()
    for i in range(10000000):
        num += 1
    lock_object.release()
    print(num)
for i in range(2):
    t = threading.Thread(target=task)
    t.start()

用with语句也是一样的

mport threading
num = 0
lock_object = threading.RLock()
def task():
    global num
    with lock_object:
        for i in range(10000000):
            num += 1
    print(num)
for i in range(2):
    t = threading.Thread(target=task)
    t.start()

除了Rlock还有Lock锁
Rlock支持多次申请锁和所赐释放,Lock不支持简单点说
Rlock支持嵌套锁,Lock不支持嵌套锁(因为会发生死锁)
有些是数据类型会在被线程调用时候被自动加线程安全
在这里插入图片描述
以下是线程不安全
在这里插入图片描述

线程池

Python3官方才正式提供线程池
线程不是开的越多越好,开的多了可能会导致系统的性能更低了
要是非常多个线程开启的话建议用线程池

import time
from concurrent.futures import ThreadPoolExecutor

future_list = []
def task(name):
    return name
def task2(name):
    future_list.append(name)
#创建线程池 最多维护10个线程
#就是线程池会自己调用给定的线程
pool = ThreadPoolExecutor(10)

for i in range(100):
    #先执行task线程
    future = pool.submit(task,i)
    #只要完事儿了再执行task的线程
    future.add_done_callback(task2)
#主线程会等待线程池完事儿后再推出
#有 pool.shutdown(True) 会让主线程等待线程池完事儿后再执行下面的内容
pool.shutdown(True)
print(future_list)
for i in future_list:
    print(i.result())
print('END')

单列模式

 import threading
class singleton:
    instance =  None
    lock = threading.RLock()
    def __init__(self,name):
        self.name = name
    def __new__(cls,*args,**kwargs):
        if cls.instance:
            return cls.instance

        with cls.lock:
            if cls.instance:
                return cls.instance
            cls.instance = object.__new__(cls)
            return cls.instance
obj1 = singleton('alex1')
print(obj1.name)
obj2 = singleton('alex2')
print(obj2.name)
print(obj1.name)

这两个对象的内存地址是一样的,但是多个线程同时创建线程时候不能百分百所有的线程都具备相同的地址,当然有锁的话就不会这样了
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值