线程方面自己写东西老出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)
这两个对象的内存地址是一样的,但是多个线程同时创建线程时候不能百分百所有的线程都具备相同的地址,当然有锁的话就不会这样了