Concurrent programming (2) as many processes 2

daemon

The main process creates a daemon

       One: the daemon will terminate after the main process code execution ends

  Second: the child process can no longer be started in the daemon process, otherwise an exception will be thrown: AssertionError: daemonic processes are not allowed to have children

Note: The processes are independent of each other. The main process code runs and the daemon process terminates immediately.

from multiprocessing import Process
import time
import random

class Piao(Process):
    def __init__(self,name):
        self.name=name
        super().__init__()
    def run(self):
        print('%s is piaoing' %self.name)
        time.sleep(random.randrange(1,3))
        print('%s is piao end' %self.name)


p = Piao ( ' egon ' )
p.daemon =True #Must be set before p.start(), set p as a daemon process, prohibit p from creating child processes, and the parent process code execution ends, p terminates running 
p.start()
 print ( ' main ' )
View Code

Process synchronization (mutex lock)

We also know before that the memory space between processes is independent, so their data is not shared, but they will definitely share the same hard disk file system, so access the same file, or the same print The terminal is completely fine. But sharing means there will be competition, and the competition between processes will lead to confusion. The way to control these problems is to lock processing.

Multiple processes share a print terminal

①, Concurrent operation, high efficiency, but competition for the same printing terminal, resulting in printing disorder

from multiprocessing import Process
import os,time
def work():
    print('%s is running' %os.getpid())
    time.sleep(2)
    print('%s is done' %os.getpid())

if __name__ == '__main__':
    for i in range(3):
        p=Process(target=work)
        p.start()

2. Lock the process and turn concurrency into serial, sacrificing operating efficiency, but ensuring security

from multiprocessing import Process,Lock
import os,time
def work(lock):
    lock.acquire() # lock, only one lock can be added
    print('%s is running' %os.getpid())
    time.sleep(2)
    print('%s is done' %os.getpid())
    lock.release() # Unlock, only after unlocking can the next lock.acquire()
if __name__ == '__main__':
    lock=Lock()
    for i in range(3):
        p=Process(target=work,args=(lock,))
        p.start()

Multiple processes share a file

① Concurrent operation, high operation efficiency, but due to competition, it will cause data confusion

#file "a.json" with content "{"count": 1}"

from multiprocessing import Process,Lock
import time,json,random

def search():
    with open('a.json','r',encoding='utf-8')as f:
        dic=json.load(f)
    time.sleep( 0.1 )
     print ( ' %s tickets remaining ' %dic[ ' count ' ])
 def get():
    with open('a.json','r',encoding='utf-8')as f:
        dic=json.load(f)
    time.sleep(0.5)
    if dic['count']>0:
        dic['count']-=1
        time.sleep(0.2)
        with open('a.json','w',encoding='utf-8')as f:
            json.dump(dic,f)
        print ( ' Successful ticket purchase ' )
 def task(lock):
    search()
    get()
if __name__ == '__main__':
    lock=Lock()
    for i in range(100):
        p=Process(target=task,args=(lock,))
        p.start()

②, lock

#file "a.json" with content "{"count": 1}"

from multiprocessing import Process,Lock
import time,json,random

def search():
    with open('a.json','r',encoding='utf-8')as f:
        dic=json.load(f)
    time.sleep(0.1)
    print('剩余 %s 张票'%dic['count'])
def get():
    with open('a.json','r',encoding='utf-8')as f:
        dic=json.load(f)
    time.sleep(0.5)
    if dic['count']>0:
        dic['count']-=1
        time.sleep(0.2)
        with open('a.json','w',encoding='utf-8')as f:
            json.dump(dic,f)
        print('购票成功')
def task(lock):
    search()
    lock.acquire()    # 只为抢票加锁,不影响其他用户查看剩余票数
    get()
    lock.release()
if __name__ == '__main__':
    lock=Lock()
    for i in range(100):
        p=Process(target=task,args=(lock,))
        p.start()

从以上结论我们可以看出互斥锁和 “join” 二者的原理是一样的,都是将并发变成并行,然而,互斥锁是让一部分代码串行(局部串行), “join” 则是让整个进程串行

总结:

#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
虽然可以用文件共享数据实现进程间通信,但问题是:
1.效率低(共享数据基于文件,而文件是硬盘上的数据)
2.需要自己加锁处理



#因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。
1 队列和管道都是将数据存放于内存中
2 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,
我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

队列

进程之间通信必须找到一种介质,该介质必须满足:

    1、是所有进程共享的

     2、必须是内存空间

最重要的是要可以自动的来处理锁的问题

创建对列的类

   Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。

参数介绍

maxsize是队列中允许最大项数,省略则无大小限制。

主要方法介绍:

1 q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。
2 q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.
3  
4 q.get_nowait():同q.get(False)
5 q.put_nowait():同q.put(False)
6 
7 q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。
8 q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。
9 q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样

了解方法:

1 q.cancel_join_thread():不会在进程退出时自动连接后台线程。可以防止join_thread()方法阻塞
2 q.close():关闭队列,防止队列中加入更多数据。调用此方法,后台线程将继续写入那些已经入队列但尚未写入的数据,但将在此方法完成时马上关闭。如果q被垃圾收集,将调用此方法。关闭队列不会在队列使用者中产生任何类型的数据结束信号或异常。例如,如果某个使用者正在被阻塞在get()操作上,关闭生产者中的队列不会导致get()方法返回错误。
3 q.join_thread():连接队列的后台线程。此方法用于在调用q.close()方法之后,等待所有队列项被消耗。默认情况下,此方法由不是q的原始创建者的所有进程调用。调用q.cancel_join_thread方法可以禁止这种行为

应用:

'''
multiprocessing模块支持进程间通信的两种主要形式:管道和队列
都是基于消息传递实现的,但是队列接口
'''

from multiprocessing import Process,Queue
import time
q=Queue(3)


#put ,get ,put_nowait,get_nowait,full,empty
q.put(3)
q.put(3)
q.put(3)
print(q.full()) #满了

print(q.get())
print(q.get())
print(q.get())
print(q.empty()) #空了
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324882446&siteId=291194637