day35

今日内容:

import time
from multiprocessing import Process, Queue
import random
# 自己理解 :两个进程之间相互进行数据传输就要通过一个中间介质,这个介质即共享文件有四种方法;
# 1,管道,单向传输,都是二进制
# 2.文件,是从硬盘中创建共享文件,再把数据传输到内存,虽然使用数据类型广,可传输的数据量大,但是传输速度慢,效率低
# 3,socket 编程复杂度较高
# 4,就是创建一种共享的容器:
# 1> Manager类 它可以开启一个共享的dict 或者list,可以提供很多数据结构
# 它所闯将出来的数据结构具备进程间共享的特点,但是出现的不明问题太多,不建议使用
# 2> Queue 类 队列 即一个容器 是极力推荐的方法,重点掌握,
# 特点:自带锁,不容易出现数据错乱的问题 先进先出
def eat(q):
# 消费
for i in range(10):
res = q.get() #从q队列中获取元素
print(res)
time.sleep(random.randint(0, 2))
print(res, "吃完了")


def mak_dog(q):
# 生产者
for i in range(10):
time.sleep(random.randint(0, 2))
print("第%s做完" % i)
res = "第%s制作完成!" % i
q.put(res) #往q中塞数据


if __name__ == '__main__':
q = Queue() #增加q队列
eat_p = Process(target=eat, args=(q,))
mak_d = Process(target=mak_dog, args=(q,))
eat_p.start()
mak_d.start()
守护进程: 作用: 父进程交给子进程一个任务,然而父进程先于子进程结束了,子进程的任务也就没必要继续执行
一个进程可以设为另一个进程的守护进程
、 特点是:被守护的进程挂了,守护进程也就挂了
p.daemon = True 呆萌
"""
互斥锁:相互排斥的锁
锁的本质就是一个标志 这个标志有两个状态 一个为锁定 一个为未锁定
用途:当多个进程要同时操作同一个资源时,就会造成数据错乱,通常将写入操作加锁,读取操作不需要加锁
加锁会把原本并发的任务,修改为串行,降低了效率吗,保证了数据的安全性
加锁可以指定一部分代码串行,其他任然可以并发

join 也可以将任务变为串行,它固定了任务的执行顺序,就是顺序固定,按顺序执行,不公平
join会是子进程的代码全部串行执行,并且主进程也会阻塞,是执行一个子进程,不能执行一行代码,他执行,别的子进程只能等待
注意:要想保证安全,必须保证大家用的都是同一把锁
不能对同一把锁连续执行acquire 将会导致锁死
from multiprocessing import Process.Lock
def task(lock):
lock.acquire()
print("任务")
lock.release()
if __name__ == '__main__':
lock = Lock() 实例化这个类
p = Process(target=task,args=(lock,))
p.start()
生产者消费者模型
def eat(q):
# 消费
for i in range(10):
res = q.get() #从q队列中获取元素
print(res)
time.sleep(random.randint(0, 2))
print(res, "吃完了")


def mak_dog(q):
# 生产者
for i in range(10):
time.sleep(random.randint(0, 2))
print("第%s做完" % i)
res = "第%s制作完成!" % i
q.put(res) #往q中塞数据


if __name__ == '__main__':
q = Queue() #增加q队列
eat_p = Process(target=eat, args=(q,))
mak_d = Process(target=mak_dog, args=(q,))
eat_p.start()
mak_d.start

其中需要队列这个容器Queue
解决双方效率,不平衡这个问题

线程
概念:线程是操作系统最小的运算调度单位,被包含在进程中,一个线程就是一个固定的执行流程
线程和进程的关系:
进程是一个资源管理单位,其包含了运行程序所需的所有资源
线程不能单独存在 必须存在于进程中,
线程才是真正的执行单位,没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程
线程可以由程序后期开启,自己开启线程称之为子线程--*************-+------------
使用线程的目的只有一个:
就是提高效率
线程如何使用:*****************重点
第一种方法:
from threading import Thread
def task():
print("子线程run")
print("子线程over"
#执行顺序不固定 如果开启线程速度足够快 可能子线程先执行
# p = Thread(target=task)
# p.start()
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print("主线程over")
结果为:子线程run
主线程over
子线程over
第二种方法:from threading import Thread
class MyThread(Thread): 继承Thread类
def run(self):
print("子线程run")
MyThread().start()
print("主线程over")
总结:使用方法和多进程方法一模一样,开启线程的代码可以放在任何位置,但是开启进程必须放在判断的下面
线程的特点:1 创建开销小
2 同一个进程中的多个线程线程数据是共享的
3,多个线程之间是平等的没有父子关系,所有线程的pid都是一样的(子进程)
案例:
from threading import Thread
import time, os
def task():
print(os.getpid())
if __name__ == '__main__':
st_time = time.time()
ts = []
for i in range(1000):
t = Thread(target=task)
t.start()
ts.append(t)
print("主线程over")
print(st_time)
了解: from multiprocessing import Process
#from threading import Thread
import time,os
def task():
print(os.getpid())

if __name__ == '__main__':
st_time = time.time()
ts =[]
for i in range(100):
t = Process(target=task)
t.start()
ts.append(t)
print("主进程over")
print(st_time)
守护线程: 一个线程可以设置为另一个线程的守护线程
主线程代码执行完毕后 不会立即结束 会等待其他子进程结束
主 会等待非守护线程结束后结束
守护线程会等到所有的非守护线程结束后结束 前提是除了主线程之外,还有别的非守护
当然如果守护线程已经完成任务。立马就结束
即如果皇帝活着,守护者 妃子死了,皇帝正常运行,皇帝死了,无论守护者是否完成任务,都立即结束
原文地址:https://www.cnblogs.com/Fzhiyuan/p/10976752.html