今天学了进程线程一些知识:
自我总结。
1.进程:在为引入线程之前,是资源调度分配的基本单位(从操作系统中得来)
2.线程:是cpu调度分配资源的基本单位
特点:进程之间是互相不影响的,不能访问彼此的资源,其中一个进程里面有多个线程,线程之间可以互相访问彼此的资源,切有一个父线程和多个子线程。
说说线程:
线程的基本调用方式要会使用,
其中有一个join()方法等同于wait()方法,是指该线程运行完了才会继续下面的操作。
而我们的创建守护线程的方法t.setDaemon()=True,必须是在线程开始运行之前设置,他在主线程结束后自动结束.
mutex互斥锁,递归锁的一些介绍
信号量的引用:
是相当于给定一定空间资源给线程,让他们最多能同时运行n个,
import threading,time
def run(n):
semp.acquire()#申明一个信号量
time.sleep(2)
print('run the thread %s\n'%n)
semp.release()#释放一个信号量
if __name__ == '__main__':
semp=threading.BoundedSemaphore(5)#创建5个信号量
for i in range(20):
t=threading.Thread(target=run,args=(i,))
t.start()
while threading.active_count()!=1:
pass
else:
print('the thread done!')
event事件:
创建一个Event对象,然后他会有两中状态,set(),clear(),设置和清除设置。
我个人是这样理解的:类似于操作系统中的阻塞,就绪,和执行,此处跟着做了一个交通灯小实验
#创建一个event事件,wait()函数相当等待事件set(),否则不运行,当我们使用set()函数之后
#可以使用clear()清除设置,有点类似于阻塞,等待,和执行
#在这里我们创建一个小汽车等红绿灯模型
import threading,time
et=threading.Event()
#红绿灯进程
def light():
count=1 #计算时间的变量
et.set()#初始设置
while True:
if count<6:
print('\033[42;1m the green light!\033[0m')
elif count>=6 and count<=10:
et.clear()
print('\033[41;1m the red light!\033[0m')
else:
et.set()
count=1#时间重置
time.sleep(1)
count+=1
lg=threading.Thread(target=light)
lg.start()
#创建一个车的进程
def car(name):
while True:
if et.is_set():#判断事件是否被设置
print('%s is running now!!!'%name)
time.sleep(1)
else:
print('%s is stop now!!!'%name)
et.wait()#若红灯结束,事件被设置在这一直等待
print('\033[32;1m green light is start! gogogo\033[0m')
ca=threading.Thread(target=car,args=('Tasla',))
ca.start()
结果如下:
在后面就是使用队列简述简单的消费者生产者问题:
我们这里引入的队列是可以称为线程队列(我自己的看法和总结)
# -*- coding: utf-8 -*-
#Author :The Y Devil
#创建一个队列来模拟缓冲池
#生产者与消费者共同使用进程来并发执行
import threading,time,queue
q=queue.Queue()
def Producer(name):
count=1
while True:
q.put("第%s骨头"%count)#把东西放入队列
print('%s 生成了%s个骨头\n'%(name,count))
count+=1
time.sleep(0.4)
def Customer(name):
while True:
print('%s 取到了 %s ,并吃掉了他\n'%(name,q.get()))#当get没有或得值时候会继续等待,
time.sleep(1)
p=threading.Thread(target=Producer,args=('付,))
p.start()
c=threading.Thread(target=Customer,args=('梁伟',))
c.start()
c1=threading.Thread(target=Customer,args=('皮皮虾',))
c1.start()
以上大致是今天学习的线程总结
进程
进程可以创建子进程:
子进程除了与父进程代码共享外,其他都为继承父进程的资源,所以彼此也是分开的互不影响的两个进程
在此获取不同进程号代码
print('当前进程名',__name__)
print("父进程号%s"%os.getppid())
print("进程名",os.getpid())
在此处主要想让自己注意的是进程的队列,我们之前引导的队列直接是
import queue
但是对于进程来说,资源互不分享,所以不回获取到线程队列,
所以我们需专门引入进程队列
from multiprocessing import Queue
此处有个例子
# -*- coding: utf-8 -*-
#Author :The Y Devil
#在之前的线程当然,队列queue可以互相访问,但是在我们的进程中每个模块都是独立的,不能互相访问
#所有要从进程模块中导入Queue
from multiprocessing import Process,Queue
import queue
#q=queue.Queue()此方法会报错,属于线程的队列
def n(q):
q.put('123')
if __name__ == '__main__':
q=Queue()#没有共享一个q队列,只是相当于克隆了一个q
x=Process(target=n,args=(q,))
x.start()
print(q.get())
两个进程管道通信:
# -*- coding: utf-8 -*-
#Author :The Y Devil
from multiprocessing import Process,Pipe
#创建一个函数,两个进程直接数据传递--管道
def talk(con):
con.send(['1',2,'i'])#两个管道互相通信,一个发送即另外个接收,相当于一次一次对接
print(con.recv())
con.close()
if __name__ == '__main__':
parent_con,child_con=Pipe()
parent_con.send('我在这')
t=Process(target=talk,args=(child_con,))
t.start()
print(parent_con.recv())
只可以同时定义两个管道,可以互相接收和发送消息,若接收时没有消息则会一直等待
如何实现数据的共享呢?
我们在multiprocessing中有一个Manage()模块,可以创建可共享的一些数据类型。
如:list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array
那我们来一起看看`
# -*- coding: utf-8 -*-
#Author :The Y Devil
from multiprocessing import Process,Manager
import os
def sa(d,l):
d[os.getpid()]=os.getpid()#把自己的pid号设置成字典
l.append(os.getpid())
#print(d)
print(l)
if __name__ == '__main__':
with Manager() as manage:#和打开文件方式有点相似
d=manage.dict( )
#d={}
l=manage.list(range(4))
p_list=[]
for i in range(10):
m=Process(target=sa,args=(d,l))
m.start()
p_list.append(m)
for res in p_list:
res.join()
print(d)
print(l)
结果:
再此处,测试一下,把manage.dict()换成普通的dict来看看结果。并在父进程和子进程内都打印,在这里屏蔽了列表的打印
每一个进程都字典都不一样,说明数据未被共享,