44_并发编程-数据共享

一、引入
    
  展望未来,基于消息传递的并发编程是大势所趋;即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合。通过消息队列交换数据。这样极大地减少了对使用锁定和其他同步手段的需求,还可以扩展到分布式系统中。
  进程间应该尽量避免通信,即便需要通信,也应该选择进程安全的工具来避免加锁带来的问题,应该尽量避免使用本节所讲的共享数据的方式,以后我们会尝试使用数据库来解决进程之间的数据共享问题。
 
二、Manager模块 - 实现数据共享
    
  1、定义
  进程间数据是独立的,可以借助于队列或管道实现通信,二者都是基于消息传递的;虽然进程间数据独立,但可以通过Manager实现数据共享,事实上Manager的功能远不止于此。
  多进程共同去处理共享数据的时候,就和我们多进程同时去操作一个文件中的数据是一样的,不加锁就会出现错误的结果,进程不安全的,所以也需要加锁
1 A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.
2 
3 A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array.
官方解释
 1 from multiprocessing import Process,Manager
 2 
 3 def func(m_dic):
 4     m_dic['name'] = 'alex_luffy'    # 子进程对数据进行了修改
 5 
 6 if __name__ == '__main__':
 7     m = Manager()
 8     m_dic = m.dict({'name':'alex'})
 9     print('主进程', m_dic)    # 先记录一下原始数据是啥样的
10     p = Process(target=func,args=(m_dic,))    # 将字典数据传递给子进程
11     p.start()
12     p.join()    # 先让子进程执行完毕
13 
14     print('主进程',m_dic)
15 结果:
16 主进程 {'name': 'alex'}
17 主进程 {'name': 'alex_luffy'}    - m_dic内的数据被子进程修改了
View Code
 
  2、创建多进程取修改子进程的数据(会出现数据不安全->会导致数据混乱加锁解决)
 1 # 设置一个100数字,创建20个进程,分别去减一
 2 
 3 from multiprocessing import Process,Manager,Lock
 4 
 5 def func(m_dic,ml):
 6     #不加锁的情况会出现数据错乱
 7     # m_dic['count'] -= 1
 8     
 9     #加锁,这是另外一种加锁形式
10     with ml:
11         m_dic['count'] -= 1
12 
13     #等同
14     # ml.acquire()
15     # m_dic['count'] -= 1
16     # ml.release()
17 
18 if __name__ == '__main__':
19     m = Manager()
20     ml = Lock()
21     m_dic = m.dict({'count':100})
22     # print('主进程', m_dic)
23     p_list = []
24 
25     #开启20个进程来对共享数据进行修改
26     for i in range(20):
27         p1 = Process(target=func,args=(m_dic,ml,))
28         p1.start()
29         p_list.append(p1)
30     [ppp.join() for ppp in p_list]
31 
32     print('主进程',m_dic)
解决数据不安全
   
  3、总结
  下面要讲的信号量和事件也相当于锁,也是全局的,所有进程都能拿到这些锁的状态,进程之间这些锁啊信号量啊事件啊等等的通信,其实底层还是socekt,只不过是基于文件的socket通信,而不是跟上面的数据共享啊空间共享啊之类的机制,我们之前学的是基于网络的socket通信,还记得socket的两个家族吗,一个文件的一个网络的,所以将来如果说这些锁之类的报错,可能你看到的就是类似于socket的错误,简单知道一下就可以啦~~~
 
 
posted @ 2018-10-25 17:58  qi.hu  阅读(201)  评论(0编辑  收藏  举报