多进程(补充),多线程,锁
Posted gengbinjia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多进程(补充),多线程,锁相关的知识,希望对你有一定的参考价值。
多进程补充
joinable Queue
q=JoinableQueue
q.put(1)
q.put(2)
print(q.get())
q.task_done() 告诉容器已经处理完成了一个数据 有几个数据就要调用几次
q.task_done()
q.join() 也是一个阻塞函数 一直到队列中的数据被处理完毕(task_done的调用次数等于队列中的数据数量)
print(‘处理完成‘)
# from multiprocessing import Process,Queue,JoinableQueue # import time,random # # # 生产者 # def make_hot_dog(q): # for i in range(1,6): # time.sleep(random.randint(1,3)) # print(" 33[46m生产者 生产了hot_dog%s 33[0m" % i) # q.put("hot_dog%s" % i) # # 消费者 # def eat_hot_dog(q): # while True: # time.sleep(random.randint(1, 2)) # hot_dog = q.get() # print("思聪吃了%s" % hot_dog) # q.task_done() # # # if __name__ == ‘__main__‘: # # 共享数据的队列 # q = JoinableQueue() # # # 生产者 # p1 = Process(target=make_hot_dog,args=(q,)) # p2 = Process(target=make_hot_dog,args=(q,)) # p1.start() # p2.start() # # # # 消费者 # c1 = Process(target=eat_hot_dog,args=(q,)) # c1.daemon = True # c1.start() # # # print("完成了吗???") # #先要确定生产者已经不会再生产了 # p1.join() # p2.join() # # print("生产已经结束了...") # #再确定队列中的所有数据都被处理完成 # q.join() # print("思聪已经全部吃完了....") # # # # c1.terminate() # #王思聪就不需要在吃了
进程池
1.多线程理论(重点)
2.多线程使用方法(重点)
两种创建方式
常用属性
锁
互斥锁
死锁
操作系统就像一个工厂
线程值的是一条流水线 整个执行过程的总称 也是一个抽象概念
线程是CPU的最小执行单位 是具体负责执行代码的
进程是一个资源单位,其中包括了改程序运行所需的所有资源
线程相当于车间里的一条流水线
线程的特点:
一个进程中至少包括一个线程 是由操作系统自动创建的 称之为主线程
一个进程中可以有任意数量的线程
创建线程的开销对比进程而言 要小的多
同一个进程中的线程间数据是共享的(最主要的特点)
如何使用:使用的方式与进程一致
不同的是:创建线程的代码可以写在任何位置
from threading import Thread
# 第一种 开启线程的方式 直接实例化Thread类 # from threading import Thread # # def task(): # print(‘running....‘) # # # if __name__ == ‘__main__‘: # t=Thread(target=task) # t.start() # print(‘over‘) # # # 2.继承Thread类 覆盖run方法 # class MyThread(Thread): # def run(self): # print(‘running...‘) # MyThread().start() # #t=MyThread() # #t.start()
开启线程速度 比开启进程快很多
主线程任务执行完毕后 进程不会立即结束 会等待所有子线程执行完毕
在同一进程中 所有线程都是平等的 没有子父一说
from threading import Thread
import time
def task():
print("子线程 running.....")
time.sleep(3)
print("子线程 over......")
t = Thread(target=task)
t.start()
print("main over")
线程与进程的区别之一 数据是共享的
区别二 创建进程与创建线程的开销 大约是一百多倍
from multiprocessing import Process import os def task(): print(os.getpid()) pass if __name__ == ‘__main__‘: start = time.time() ps = [] for i in range(100): p = Thread(target=task) # p = Process(target=task) p.start() ps.append(p) for p in ps: p.join() print(time.time()-start)
线程安全也是通过锁来保证 所得用法与进程中一模一样
# import time # from threading import Thread,Lock # # num = 10 # lock = Lock() # # def task(): # global num # # lock.acquire() # a = num # time.sleep(0.1) # num = a - 1 # # lock.release() # # # ts = [] # for i in range(10): # t = Thread(target=task) # t.start() # ts.append(t) # # for t in ts: # t.join() # # # print(num)
开发高并发程序很有可能遇到安全问题
解决方案只有加锁 但是在使用锁时 很有可能出现死锁问题
出现死锁问题的两种情况:
1.对同一把锁调用了多次acquire 导致死锁问题(最low的死锁问题 应该避免这种问题)
2.有多把锁,一个线程抢一把锁,要完成任务必须同时抢到所有的锁 将导致死锁问题
from threading import Lock,Thread import time # lock = Lock() # lock.acquire() # lock.acquire() # print("over") # 一个盘子 和一双筷子 # lock1 = Lock() # lock2 = Lock() # # def task1(name): # lock1.acquire() # print("%s 抢到了盘子" % name) # # time.sleep(1) # # lock2.acquire() # print("%s 抢到了筷子" % name) # # print("%s 吃饭了....." % name) # # lock1.release() # lock2.release() # # # def task2(name): # lock2.acquire() # print("%s 抢到了筷子" % name) # # lock1.acquire() # print("%s 抢到了盘子" % name) # # print("%s 吃饭了....." % name) # # lock1.release() # lock2.release() # # # # t1 = Thread(target=task1,args=("渣渣辉",)) # t1.start() # # t2 = Thread(target=task2,args=("大导演",)) # t2.start()
如何避免:
1.能不加锁就不加
2.如果一定要加 要保证锁只有一把
RLock只能防止同一个问题 统一线程多次执行acquire
from threading import RLock # lock = RLock() # lock.acquire() # lock.acquire() # lock.acquire() # lock.acquire() # # print("over") # lock = RLock() # # def task1(): # lock.acquire() # def task2(): # lock.acquire() # # Thread(target=task1).start() # Thread(target=task2).start()
信号量 Semaphore(num) 可以控制同一时间有多少线程可以并发的访问
不是用来处理线程安全问题
from threading import Semaphore s_lock = Semaphore(3) def task(): s_lock.acquire() time.sleep(1) print("run.....") s_lock.release() for i in range(20): t = Thread(target=task) t.start()
threading.current_thread() # 获取当前线程
threading.active_count() 正在运行中的线程数量
threading.enumerate() 返回所有正在运行的线程对象
守护线程会在主线程结束后立即结束 即使任务没有完成
主线程会等待所有子线程全部完成后才会结束
守护线程会在所有非守护线程结束后 结束*****
主线 守护线程
主线程要等待所有子线程结束
from threading import Semaphore s_lock = Semaphore(3) def task(): s_lock.acquire() time.sleep(1) print("run.....") s_lock.release() for i in range(20): t = Thread(target=task) t.start()
以上是关于多进程(补充),多线程,锁的主要内容,如果未能解决你的问题,请参考以下文章