一、进程的数据共享
进程间数据是独立的,可以借助于队列或管道实现通信,二者都是基于消息传递的
虽然进程间数据独立,但可以通过Manager实现数据共享。把所有实现了数据共享的比较便捷的类都重新又封装了一遍,并且在原有的multiprocessing基础上增加了新的机制 list dict等数据共享的机制支持数据类型非常有限list dict都不是数据安全的,你需要自己加锁来保证数据安全Manager用法:
Manager().dict()  # 创建共享的字典
Manager().list()  # 创建共享的列表

用代码看看:
简单解释一下with:
with可以自动关闭文件、线程锁的自动获取和释放等事后清理工作。
紧跟with后面的语句会执行对象的 __enter__() 方法,这个方法的返回值将被赋值给as后面的变量。
当with后面的代码块全部被执行完之后,将调用对象的 __exit__()方法。from multiprocessing import Manager,Process,Lock
def work(dic,lock):with lock:   # 多个进程对数据进行修改,不加锁的话会导致数据不安全dic['count'] -= 1   # 每个进程都对dic进行修改if __name__ == '__main__':lock = Lock()with Manager() as m:dic = m.dict({'count':100})  # 创建共享的字典p_lst = []for i in range(100):p = Process(target=work,args=(dic,lock))p_lst.append(p)p.start()for p in p_lst:p.join()print(dic)二、进程池的回调函数(同步提交apply没有回调函数)
场景:
子进程有大量的计算要去做,回调函数对结果做简单处理。
我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。通过例子了解一下:
import os
from multiprocessing import Pooldef func(i):print('子进程:',os.getpid())return idef call_back(res):print('回调函数:',os.getpid())print('res--->',res)if __name__ == '__main__':p = Pool()print('主进程:',os.getpid())p.apply_async(func,args=(1,),callback=call_back)  # callback关键字传参,参数是回调函数
    p.close()p.join()结果:
主进程: 4732
子进程: 10552
回调函数: 4732
res---> 1从结果可以看出:子进程func执行完毕之后才去执行callback回调函数子进程func的返回值会作为回调函数的参数回调函数是在主进程中执行的应用实例:url_lst = ['http://www.baidu.com','http://www.4399.com','http://www.163.com','http://www.hao123.com','http://www.sina.com'
]import re
from urllib.request import urlopen
from multiprocessing import Pooldef get_url(url):res = urlopen(url) # 打开链接web_name = re.search('www\.(.*)\.com',url) # 网站名print('%s finish' %web_name.group(1))return web_name.group(1),res.read()  # 返回网站名和连接的内容def call_back(content):  # 把链接的内容写入文件web_name,con = contentwith open(web_name+'.html','wb') as f:f.write(con)if __name__ == '__main__':p = Pool()for url in url_lst:p.apply_async(get_url,args=(url,),callback=call_back)p.close()p.join()三、线程的理论知识
1、进程概念
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。
程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。
这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的2、进程的缺点
进程只能在一个时间做一件事,不能同时做两件事或多件事
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行3、线程的概念
60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,
因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。因此在80年代,出现了能独立运行的基本单位——线程(Threads)。注意:进程是资源分配的最小单位,线程是CPU调度的最小单位.每一个进程中至少有一个线程。4、进程和线程的关系
1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2)通信:进程间通信需要IPC(队列,管道等),同一个进程中的所有线程的资源是共享的
3)调度和切换:线程上下文切换比进程上下文切换要快得多。
4)在多线程操作系统中,进程不是一个可执行的实体5、线程使用场景
当某个进程肯定需要做不止一件事情的时候,比如你用QQ,你可以同时跟很多人聊天,而QQ只是一个进程,并不是说你跟一个人聊天就开一个进程这样,
因为聊天这些任务操作的都是同一块数据,因而不能用多进程。应该是你开了QQ这个进程,跟别人聊天的时候在这个进程里开启多个线程跟别人聊天。6、线程的理解
多个线程共享同一个进程的地址空间中的资源,是对一台计算机上多个进程的模拟,有时也称线程为轻量级的进程。
同一台计算机上多个进程,则共享这台计算机的物理内存、磁盘、打印机等其他物理资源。多线程的运行跟多进程的运行类似,是cpu在多个线程之间的快速切换。
不同的进程之间是充满敌意的,彼此是抢占、竞争cpu的关系,比如QQ和迅雷抢资源。而同一个进程是由一个程序员的程序创建,所以同一进程内的线程是合作关系,一个线程可以访问另外一个线程的内存地址,大家都是共享的。
类似于进程,每个线程也有自己的堆栈,不同于进程,线程库无法利用时钟中断强制线程让出CPU,可以调用thread_yield运行线程自动放弃cpu,让另外一个线程运行。7、用户级线程和内核级线程
用户级线程
内核的切换由用户态程序自己控制内核切换,不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核Cpu。
在用户空间模拟操作系统对进程的调度,来调用一个进程中的线程,每个进程中都会有一个运行时系统,用来调度线程。此时当该进程获取cpu时,进程内再调度出一个线程去执行,同一时刻只有一个线程执行。内核级线程
切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态;可以很好的利用多核cpu,windows线程就是这样的。混合实现
用户级与内核级的多路复用,内核同一调度内核线程,每个内核线程对应n个用户线程8、python中的线程
全局解释器锁GIL
一个进程中的多个线程能够并行么?在java  c++  c# 等语言中是可以的
    但是在python中是不可以的python是一个解释型语言,所有的解释型语言都不行为什么不行?
Cpython解释器内部有一把全局解释器锁 GIL
同一时刻用一个进程中的线程只有一个能被CPU执行
所以线程不能充分的利用多核GIL锁是为了保证数据的安全性,虽然确实是限制了你的程序效率
但实际上GIL锁是目前能够帮助你在线程的切换中提高效率的手段9、总结
进程是计算机中最小的资源分配单位进程对于操作系统来说还是有一定负担创建一个进程 操作系统要分配的资源大致有 :代码数据文件为什么要有线程轻量级的概念他没有属于自己的进程资源:一条线程只负责执行代码,没有自己独立的代码、变量、文件资源什么是线程线程是计算机中被CPU调度的最小单位你的计算机当中的cpu都是执行的线程中的代码线程和进程之间的关系每一个进程中都有至少一条线程在工作线程的特点同一个进程中的线程共享这个线程的所有资源轻量级 没有自己的资源进程和线程之间的区别占用的资源调度的效率资源是否共享通用的问题一个进程中的多个线程能够并行么?在java c++ c# 等语言中是可以的

python中的线程在python中一个进程中的多个线程能够并行么? 不行python是一个解释型语言,所有的解释型语言都不行为什么不行?Cpython解释器 内部有一把全局解释器锁 GIL所以线程不能充分的利用多核同一时刻用一个进程中的线程只有一个能被CPU执行GIL锁是为了保证数据的安全性,虽然确实是限制了你的程序效率但实际上GIL锁是目前能够帮助你在线程的切换中提高效率的手段GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。线程有:
IO密集型线程和计算密集型线程
cpython解释器适合IO密集型线程(web 爬虫 金融分析)如果要写计算密集型的线程:
要么换解释器,要么用多进程四、threading模块
multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性
1、线程的创建方式
方式一:
from threading import Thread
import timedef sleep_boy(name):time.sleep(1)print('%s is sleeping' %name)t = Thread(target=sleep_boy,args=('xiaoming',))  # 这里可以不需要main,因为现在只是在一个进程内操作,不需要导入进程就不会import主进程了
t.start()
print('主线程')方式二:
from threading import Thread
import timeclass Sleep_boy(Thread):def __init__(self,name):super().__init__()self.name = namedef run(self):time.sleep(1)print('%s is sleeping' % self.name)t = Sleep_boy('xiaoming')
t.start()
print('主线程')2、并发性(注意:在主进程下开启多个线程,每个线程的pid都跟主进程的pid一样)
import os
import time
from threading import Threaddef func(i):time.sleep(0.5)print('子线程:',i,os.getpid())print('主进程:',os.getpid())
for i in range(10):t = Thread(target=func,args=(i,))t.start()3、线程共享进程的资源
from threading import Threadnum = 100  # 全局变量def func():global numnum -= 1t_lst = []
for i in range(100):t = Thread(target=func)t.start()t_lst.append(t)
for t in t_lst:t.join()
print('num:',num)4、其他方法
Thread实例对象的方法isAlive(): 返回线程是否活动的。is_alive(): 返回线程是否活动的。getName(): 返回线程名。setName(): 设置线程名。from threading import Thread
import time
def func():time.sleep(0.2)print('hello')
t = Thread(target=func)
t.start()
print(t.isAlive())  # True
print(t.is_alive()) # True
print(t.getName())  # Thread-1
t.setName('t1')
print(t.getName())  # t1
threading模块提供的一些方法:threading.currentThread(): 返回当前线程的对象(通过这个对象可以查看线程的一些属性,比如线程id:ident,线程的名字:getName等)threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。from threading import currentThread,enumerate,activeCount,Thread
import time
def func():print('子线程:',currentThread().ident)     # 子线程: 6076print('子线程:',currentThread().getName()) # 子线程: Thread-1time.sleep(3)print('主线程:',currentThread().ident)      # 主线程: 1156
print('主线程:',currentThread().getName())  # 主线程: MainThread
t = Thread(target=func)
t.start()
print(enumerate())  # [<_MainThread(MainThread, started 1156)>, <Thread(Thread-1, started 6076)>]
print(len(enumerate())) # 2
print(activeCount())    # 25、守护线程
守护进程和守护线程的区别:1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,所以主线程结束了之后,守护线程随着主进程的结束自然结束了import time
from threading import Thread
def func1():while True:time.sleep(0.5)print('func1')def func2():print('func2 start')time.sleep(3)print('func2 end')t1 = Thread(target=func1)
t2 = Thread(target=func2)
t1.setDaemon(True)  # 设置守护线程# t1.daemon = True   t1 = Thread(target=func1,daemon = True)  这两种方式也是开启守护线程的方法
t1.start()
t2.start()
print('主线程代码结束了')
守护进程:只能用 p.daemon = True 这种方式设置守护进程,因为daemon只是Process类对象的属性,而守护线程,可以使用 t1 = Thread(target=func1,daemon = True)和t1.daemon = True这两种方式和t1.setDaemon(True)这种方法设置守护线程因为daemon是Thread类对象的属性和对象的默认参数

守护进程(一种方式)p = Process(target=func)p.daemon = True  # daemon是Process的属性

守护线程(三种方式)t1 = Thread(target=func1,daemon = True)t1.daemon = Truet1.setDaemon(True)

进程:

线程:

转载于:https://www.cnblogs.com/yidashi110/p/10092149.html

进程间的数据共享、进程池的回调函数和线程初识、守护线程相关推荐

  1. Python之进程+线程+协程(进程间通信、进程同步、进程池、回调函数)

    文章目录 进程间通信 进程同步 进程池 回调函数 本篇文章依然是进程.线程方面的内容,主要讲进程间的通信.进程队列.进程同步.进程池.进程同步和回调函数 进程间通信 进程就是两个独立的内存空间在运行, ...

  2. Python之路 34:并发与并行、锁(GIL、同步锁、死锁与递归锁)、信号量、线程队列、生消模型、进程(基础使用、进程通信、进程池、回调函数)、协程

    内容: 同步锁 死锁.递归锁 信号量和同步对象(暂时了解即可) 队列------生产者和消费者模型 进程(基础使用.进程通信.进程池.回调函数) 协程 一.并发并行与同步异步的概念 1.1.并发和并行 ...

  3. python全栈开发,Day40(进程间通信(队列和管道),进程间的数据共享Manager,进程池Pool)...

    昨日内容回顾 进程 multiprocess Process -- 进程 在python中创建一个进程的模块startdaemon 守护进程join 等待子进程执行结束锁 Lock acquire r ...

  4. python并发处理list数据_python并发编程之多进程2--------数据共享及进程池和回调函数...

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

  5. 进程池、线程池、回调函数、协程

    阅读目录 摘要: 进程池与线程池 同步调用和异步调用 回调函数 协程 一.进程池与线程池: 1.池的概念: 不管是线程还是进程,都不能无限制的开下去,总会消耗和占用资源. 也就是说,硬件的承载能力是有 ...

  6. python进程数据共享_python程序中的进程操作-进程间的数据共享

    展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合,通过消息队列交换数据. 这样极大地减少了对使用锁定和其他同步手段的需求,还可以扩展到分布式系统中 ...

  7. 5进程间锁:进程间pthread_mutex,文件锁

     1进程间pthread_mutex A依赖的头文件 #include<pthread.h> B函数声明 int pthread_mutexattr_destroy(pthread_m ...

  8. linux 进程间切换,linux 进程管理 进程切换

    2.Arm体系架构中进程切换过程 在之后的文章里,可能会有很大部分的篇幅是介绍内核如何调度和管理进程.学习了解这部分内容,很多时候是和task struct,run queue,schedule en ...

  9. python 进程间同步_python之路29 -- 多进程与进程同步(进程锁、信号量、事件)与进程间的通讯(队列和管道、生产者与消费者模型)与进程池...

    所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了.至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠 ...

最新文章

  1. Python 人脸识别就多简单,看这个就够了!
  2. Redis Cluster原理初步
  3. ruby 执行函数_Ruby at()函数
  4. python中ans的用法_python cx_Oracle基础使用方法
  5. 纯HTML、CSS实现下拉菜单
  6. java画虚线_在java中绘制虚线
  7. 用计算机来猜密码,画圈圈也能解锁电脑?我猜你一定不知道!
  8. 神技能!在上司靠近座位时,用人脸识别技术及时屏幕切换
  9. 力扣——算法入门计划第十四天
  10. java swing实现文件浏览器功能小程序
  11. 《实用C语言编程》读书笔记
  12. 天津仁爱学院ACM工作室简介
  13. 免费录屏软件哪个好用 ? 7 款免费又好用的录屏工具 , 打工人必备
  14. ROUND_UP、ROUND_DOWN、ROUND_HALF_UP(BigDecimal四舍五入)、ROUND_HALF_DOWN
  15. 计算机数据采集管理系统的结构和功能,生产数据采集系统结构、功能及特点
  16. 2.12 二项式系数加法解 C实现
  17. 非功能性需求之性能需求分析
  18. 几种SFTP SSH工具
  19. 什么是去中心化市场(OpenBazaar)
  20. 王劲说无人车是他的终身事业,他要重回行业一线!

热门文章

  1. 关东升的《从零开始学Swift》即将出版
  2. 如何建立自己的光纤网络来连接数据中心
  3. 文件共享服务器如何提高网速,怎么提高网速 提高网速方法【详细介绍】
  4. 用户在离开计算机锁定功能,短暂离开也不怕 轻松锁定保护用户隐私(2)
  5. python中元组的概念_python元组的概念与基本操作
  6. 质因数分解求给定正整数的因数个数
  7. 1、树莓派使用FFMPEG推流到PC端显示
  8. python爬取百度搜索_Python-Scrapy抓取百度数据并分析
  9. 使用高斯混合模型(GMM)近似未知分布:EM算法的应用
  10. 【原创】Unity3D 怪物散步、战斗、追击 AI