1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 3 进程间通信IPC机制 线程 线程通信 互斥锁

3 进程间通信IPC机制 线程 线程通信 互斥锁

时间:2020-07-07 11:09:01

相关推荐

3 进程间通信IPC机制 线程 线程通信 互斥锁

今日内容:

1,进程间的相互通信

2,生产者消费者模型

3,线程

4,线程间通信

5,线程互斥锁

1,进程间相互通信 IPC 机制

1,基于队列来实现通信Queue,队列就相当于管道+锁

队列:先进先出

堆栈:先进后出

from multiprocessing import Queue

q = Queue(5) # 括号内可以传参数 表示的是这个队列的最大存储数

q.put(1)

q.put(2)

q.put(3)

q.put(4)

q.put(5)向队列中添加数据

print(q.full()) 判断队列是否满了,Ture 或 False

q.get()

q.get()

print(q.empty()) 判断队列中的数据是否被取完

print(q.get()) 从队列中获取数据

print(q.get())

print(q.get())

print(q.get_nowait()) # 取值 没有值不等待,直接报错

ps:get与put要对应,数量一致,put一次只能从队列中添加一个值,get一次只能拿出一个值

如果get的数量比put的多,则队列中的值被取完了,此时不会报错,

就会等待(阻塞),等队列中有值加入时,继续取值操作,同理 put增加值时也是一样的

即q.put(6) # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态)

当队列中的数据被取完之后 再次获取 程序会阻塞 直到有人往队列中放入值

补充:

full(), q.empty(), q.get_nowait() 都不适用于多进程的情况下

案列: from multiprocessing import Process,Queue

def scz(q): 要把队列的对象传进来*****

q.put('hello')

def xfz(q):

print(q.get())

if __name__ == '__main__':

q = Queue()

p = Process(target=scz,args=(q,))

p1 = Process(target=xfz,args=(q,))

p.start()

p1.start()

总结:两个进程之间通信,是通过队列来实现的,把 产生的数据放在队列中,让另一个进程提取

在这里要注意的是要把队列对象作为参数分别传给两个进程

2,生产者消费者模型

问题:解决供需不平衡的问题

生产者:生产或者制造数据的做包子的

消费者:来筛选或者处理数据 买包子的

案列:(不能让阻塞在data = q.get()位置)

from multiprocessing import Process,JoinableQueue,Queue

import time

import random

def scz(name,food,q):

for i in range(0,10):

data = ('%s生产了%s包子%s'% (name,food,i))

time.sleep(0.5)

q.put(data)

print(data)

def xfz(name,q):

while True:

data = q.get()

if data == None: break # 如果data为None,说明队列中的数据已被取完

print('%s 吃掉了%s包子'% (name,data))

time.sleep(random.random())

q.task_done() # 告诉队列从队列中已取出一个数据,并且已经全部处理完毕,结束任务 *****

if __name__ == '__main__':

# q = Queue()

q = JoinableQueue()# *******

p = Process(target=scz, args=('111', '牛肉馅', q))

p1 = Process(target=scz, args=('盘龙', '白菜馅', q))

c = Process(target=xfz, args=('开门', q))

c1 = Process(target=xfz, args=('芝麻', q))

c.daemon = True

c1.daemon = True

p.start()

p1.start()

c.start()

c1.start()

#这种方法太low了

# p.join() # 确保生产者确确实实生产完了

# p1.join() # 确保生产者确确实实生产完了

# q.put(None) # 生产者生产完在队列增加一个值 None, 当取值取到None时说明队列中的数据取完了

# q.put(None) # 一个消费者用一个None,两个消费者就得用两个None ,一个消费者只要接受到none,立马结束!

# 高级方法

p.join() # 确保生产者确确实实生产完了

p1.join()

q.join() # 等到队列中的数据全部被取出 *******

3,线程

1,线程:最小的执行单位

2,进程:资源单位

将内存比作工厂,那么进程就是车间,线程就是车间里的流水线

ps:每个进程都自带一个主线程,线程是最小的执行单位,进程只是为了给线程提供资源或者代码

在进程中,每个线程都是共享进程资源

开启线程的销号要远远小于进程

进程:开辟内存空间,太耗资源

拷贝代码: 耗资源

开启线程的两种方式:

ps:开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内

from threading import Thread

import time

def task(name):

print('tttttu%s'% name)

time.sleep(1)

print('11111')

p = Thread(target=task,args=('teek',))

p.start() 告诉操作系统开辟一个线程 线程的开销远远小于进程

print('zhu')

第二种方式:

class MyThread(Thread):

def __init__(self,name):

super().__init__()

self.name = name

def run(self):

print("%s 是个大帅哥!"% self.name)

time.sleep(0.1)

print('但是%s疯了!'% self.name)

p = MyThread('张文诶诶')

p.start() # 启动线程

print('zhu')

线程的其他方法:

from threading import Thread,current_thread,active_count

1,current_thread 查看主线程或者子线程

print('子current_thread:',current_thread().name)

线程没有自主之分,都是平等的,在这里为了区分,才这样讲

2,active_count 查看线程是否存活

print('当前正在活跃的线程数',active_count())

3,获取子线程号

print('子',os.getpid())

守护线程:

主线程的结束也就意味着进程的结束

主线程必须等待其他非守护线程的结束才能结束

(意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)

案列:

from threading import Thread

import time

def task(i):

time.sleep(i)

print('tt’)

t = Thread(target=task,args=(1,))

t.daemon = True

t.start()

print('主')主

4, 线程间通信

同一个进程的资源所有线程都可用,即数据共享

money = 666

def task():

global money

money = 999

t = Thread(target=task)

t.start()

t.join()

print(money)

5,线程互斥锁:

当多个线程或者进程想要操作同一份数据时,必须加锁,防止数据错乱!

案列:

from threading import Thread,Lock

import time

n = 100

def task(m):

global n

m.acquire()

tmp = n

time.sleep(0.1)

n = tmp -1

m.release()

tt = []

m = Lock()

for i in range(100):

t = Thread(target=task,args=(m,))

t.start()

tt.append(t)

for t in tt:

t.join()

print(n)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。