from multiprocessing import JoinableQueue
q = JoinableQueue()
# q.get()
q.put('123')
q.put('678')
q.task_done()#用来发送一个任务完成的信号
q.task_done()
print('...........')
q.join()#等待队列中的数据被处理完毕
print('over')
'''
注:jion会等待队列中所有的数据处理完毕,一个put需要对应一个task_done,当队列取空时调用task_done会出现 valueerro异常.
虽然task_done用来发送一个任务完成得信号,但是队列并不会关心你有没有取出数据,就是调用get函数
'''
生产者消费者模型中使用joinblequeue
import random
import time
from multiprocessing import Process, Queue,JoinableQueue
def make_hotdog(name,q):
for i in range(5):
time.sleep(random.randint(1,3))
print("%s生产了热狗%s" % (name,i))
q.put("%s的%s号热狗" % (name,i))
# q.put(None)
def eat_hotdog(name,q):
while True:
hotdog = q.get()
# if not hotdog:
# break
time.sleep(random.randint(1, 3))
print("%s吃掉了%s" % (name,hotdog))
# 必须记录 该数据 处理完成了
q.task_done()
if __name__ == '__main__':
q = JoinableQueue()
p = Process(target=make_hotdog,args=("owen的热狗店",q))
p2 = Process(target=make_hotdog,args=("bgon的热狗店",q))
p3 = Process(target=make_hotdog,args=("jerry的热狗店",q))
c = Process(target=eat_hotdog,args=("思聪",q))
c.daemon = True
c2 = Process(target=eat_hotdog, args=("大葱", q))
c2.daemon = True
# c3 = Process(target=eat_hotdog, args=("二葱", q))
p.start()
p2.start()
p3.start()
c.start()
c2.start()
# c3.start()
# 目前的思路 是当商家做完以后 放一个None 作为结束标志 不够好 必须明确商家和消费者的个数
# 明确商家生成完毕 在明确消费者吃完了 就算结束
p.join()
print("第一家生成完毕")
p2.join()
print("第二家生成完毕")
p3.join()
print("第三家生成完毕")
# 消费者吃完了
q.join()
print("消费吃完了!")
print("美好的一天结束了!")
线程
# 线程 线程是操作系统最小的运算调度单位,线程别包含在进程中
# 进程根本不能被执行,它是一个资源单位,其包含了运行程序的所有资源,线程才是执行单位
# 没有线程,进程中的资源无法被利用起来.所以一个进程至少包含一个线程,称之为主线程
# 当我们启动一个程序时,操作系统就会自己为这个程序创建一个主线程
# 线程可以由程序后期开启,自己开启线程称之为子线程.但是不要误会,线程之间并没有父子关系
# 开启多个线程主要为了提高效率
#同一个进程中的线程数据时共享的
#创建线程比创建进程的开销小
from threading import Thread
def task():
print(1 + 1)
print('子线程running')
t = Thread(target=task)
#守护线程
t.deamon = True
t.start()
print('主线程over')
class MyThread(Thread):
def run(self):
print('子线程')
MyThread().start()
#守护线程得概念和守护进程一样,值得注意,守护线程在自己得代码执行完毕以后就死亡了,只有在代码没有执行完,主程死亡了,守护进程才会跟着一起死亡,主进程需要等待非守护进程结束才能结束
多线程
#线程间数据共享实例
from threading import Thread
a = 10
def task():
global a
print('子线程........')
a = 20
t = Thread(target=task)
t.start()
t.join()#主线程等待子线程执行完毕
print(a)
#不能像进程一样将a作为参数传过去,因为我们用类和函数来表示线程和线程要执行得代码,所以传过去在python语法中就时两个变量了
线程的安全问题
#锁
from threading import Thread,enumerate,Lock
import time
number = 10
lock = Lock()
def task():
global number
lock.acquire()
a = number
time.sleep(0.1)
number = a - 1
lock.release()
for i in range(10):
t = Thread(target=task)
t.start()
for t in enumerate()[1:]:
# print(t)
t.join()
print(number)
# 用于访问当前正在运行的所有线程
# print(enumerate())
#死锁
'''当程序出现了不止一把锁,分别被不同的线程持有, 有一个资源要想使用必须同时具备两把锁
这时候程序就会进程无限卡死状态 ,这就称之为死锁
'''
import time
# 盘子
lock1 = Lock()
# 筷子
lock2 = Lock()
def eat1():
lock1.acquire()
print("%s抢到了盘子" % current_thread().name)
time.sleep(0.5)
lock2.acquire()
print("%s抢到了筷子" % current_thread().name)
print("%s开吃了!" % current_thread().name)
lock2.release()
print("%s放下筷子" % current_thread().name)
lock1.release()
print("%s放下盘子" % current_thread().name)
def eat2():
lock2.acquire()
print("%s抢到了筷子" % current_thread().name)
lock1.acquire()
print("%s抢到了盘子" % current_thread().name)
print("%s开吃了!" % current_thread().name)
lock1.release()
print("%s放下盘子" % current_thread().name)
lock2.release()
print("%s放下筷子" % current_thread().name)
t1 = Thread(target=eat1)
t2 = Thread(target=eat2)
t1.start()
t2.start()
RLOCK和信号量
'''
Rlock 称之为递归锁或者可重入锁
Rlock不是用来解决死锁问题的
与Lock唯一的区别:
Rlock同一线程可以多次执行acquire 但是执行几次acquire就应该对应release几次
如果一个线程已经执行过acquire 其他线程将无法执行acquire
'''
"""
信号量 了解
Semaphore
用途: 仅用于控制并发访问 并不能防止并发修改造成的问题
"""
from threading import Semaphore, Thread
import time
s = Semaphore(5)#参数用于表示可以由多少并发访问
def task():
s.acquire()
print("子run")
time.sleep(3)
print("子over")
s.release()
for i in range(10):
t = Thread(target=task)
t.start()