操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁
并发编程前言:
1、网络应用
1)爬虫 直接应用并发编程;
2)网络框架 django flask tornado 源码-并发编程
3)socketserver 源码-并发编程
2、运维领域
1)自动化开发-运维开发(机器的批量管理,任务的批量执行等)
一、操作系统/应用程序
a、硬件
- 硬盘
- CPU
- 主板
- 显卡
- 内存
- 电源
. . . . . .
b、装系统(软件)
- 系统就是一个由程序员写出来的软件,该软件用于控制计算机的硬件,让他们之间进行相互配合。
c、安软件(安装应用程序)
- 百度云
- pycharm
. . . . . .
二、并行与并发
并发,是伪的,由于执行速度特别快,人感觉不到停顿;
并行,是真的,创建10个人同时操作;
并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑(资源够用,比如三个线程,四核的cpu);
并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核cpu资源)同时只能过一个人,A走一段后,让给B,B用完继续给A,交替使用,目的是提高效率;
区别:
并行是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。
并发是从宏观上,在一个时间段上可以看成是同时执行的。
三、线程和进程
a、单进程、单线程的应用程序,比如:
print('666')
b、到底什么是线程?什么是进程?
python自己没有这玩意,python中调用的操作系统的线程和进程。
c、单进程、多线程的应用程序,比如:
import threading
print('') def func(arg):
print(arg)
t = threading.Thread(target=func,args=(11,)) # 创建一个线程
t.start()
一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)。
d、故事:Alex甄嬛西游传
总结:
1)操作系统帮助开发者操作硬件;
2)程序员写好代码在操作系统上运行(依赖解释器);
3)任务比较多时,可将以前代码写法作如下改进:
import requests
import uuid url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
] def task(url):
ret = requests.get(url)
file_name = str(uuid.uuid4()) + '.jpg'
with open(file_name, mode='wb') as f:
f.write(ret.content) for url in url_list:
task()
"""
- 我们写好代码
- 交给解释器运行: python s1.py
- 解释器读取代码,再交给操作系统去执行,根据我们的代码去选择创建多少个线程/进程去执行(此程序是单进程/单线程)。
- 操作系统调用硬件:硬盘、cpu、网卡....
"""
以前的我们写代码
import threading
import requests
import uuid url_list = [
'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
] def task(url):
ret = requests.get(url)
file_name = str(uuid.uuid4()) + '.jpg'
with open(file_name, mode='wb') as f:
f.write(ret.content) for url in url_list:
t = threading.Thread(target=task, args=(url,)) # 创建线程
t.start()
"""
- 你写好代码
- 交给解释器运行: python s2.py
- 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(此程序是单进程/4线程)。
- 操作系统调用硬件:硬盘、cpu、网卡....
"""
现在的我们写代码
四、python中线程和进程(GIL锁)
GIL锁:python内置的一个全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调度。
扩展:默认GIL锁再执行100个cpu指令(过期时间)。
import sys
v = sys.getcheckinterval()
print(v) #
查看方法
问题1:为什么有这把GIL锁?
python语言的创始人在开发这门语言时,目的是快速把语言开发出来,如果加上GIL锁(c语言加锁),切换时按照100条字节指令来进行线程间的切换。
问题2:进程和线程的区别?
线程,线程是cpu工作的最小单元;
进程,进程是cpu资源分配的最小单元,为线程提供一个资源共享的空间;
一个进程中可以有多个线程,一个进程中默认有一个主线程;
对于python来说,它的进程和线程和其他语言有差异,有GIL锁。它保证一个进程中同一时刻只有一个线程被cpu调度;
IO密集型操作可以使用多线程,计算密集型可以使用多进程;
问题3:线程创建的越多越好吗?
不是,线程之间进行切换,要做上下文管理。
五、python线程编写
1、线程的基本使用,如下示例:
import threading
def func(arg):
print(arg) t = threading.Thread(target=func,args=(11,)) # 创建一个子线程
t.start() print(123)
#
#
# 程序结束
2、主线程默认等子线程执行完毕,才结束程序,如下示例:
import threading
import time
def func(arg):
time.sleep(arg)
print(arg) t1 = threading.Thread(target=func,args=(3,))
t1.start() t2 = threading.Thread(target=func,args=(6,))
t2.start()
# 3 # 程序开始3秒后
# 6 # 程序开始6秒后
# 程序结束
3、主线程不再等,当主线程终止则所有子线程也终止,使用setDaemon(True),如下示例:
import threading
import time
def func(arg):
time.sleep(arg)
print(arg) t1 = threading.Thread(target=func,args=(3,))
t1.setDaemon(False) # 主线程等待此子进程
t1.start() t2 = threading.Thread(target=func,args=(6,))
t2.setDaemon(True) # 主线程不再等待此子进程
t2.start() print(123)
#
#
# # 程序结束
4、开发者可以控制主线程等待子线程(最多等待时间),使用join(n),如下示例:
import threading
import time
def func(arg):
time.sleep(arg)
print(arg) print('创建子线程t1')
t1 = threading.Thread(target=func,args=(3,))
t1.start()
t1.join(2)
# 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
# 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。 print('创建子线程t2')
t2 = threading.Thread(target=func,args=(1,))
t2.start()
t2.join(3) # 让主线程在这里等着,最多等待3秒,会继续往下走,
# 若子线程t2不到3秒就执行完毕,则子线程执行完毕主线程就往下走。 print(123)
# 创建子线程t1
# 创建子线程t2
#
#
#
# 程序结束
5、线程名称,如下示例:
import threading
def func(arg):
t = threading.current_thread() # 获取当前执行该函数的线程的对象
name = t.getName() # 根据当前线程对象获取当前线程名称
print(name,arg) t1 = threading.Thread(target=func,args=(11,))
t1.setName('郭德纲') # 设置线程名称
t1.start() t2 = threading.Thread(target=func,args=(22,))
t2.setName('孙红雷') # 设置线程名称
t2.start() print(123)
# 郭德纲 11
# 孙红雷 22
#
6、线程本质,如下示例:
# 先打印:11?123?
import threading
def func(arg):
print(arg) t1 = threading.Thread(target=func,args=(11,))
t1.start()
# start 是开始运行线程吗?不是
# start 告诉cpu,我已经准备就绪,你可以调度我了。
print(123)
7、面向对象版本的多线程,如下示例:
import threading
def func(arg):
print(arg) t1 = threading.Thread(target=func,args=(11,))
t1.start()
常见创建多线程的方式:
import threading
class MyThread(threading.Thread):
def run(self):
print(11111,self._args,self._kwargs) t1 = MyThread(args=(11,))
t1.start() # 在cpu内部,如果要调度这个线程的话会执行这个对象的run方法 t2 = MyThread(args=(22,))
t2.start() print('end')
# 11111 (11,) {}
# 11111 (22,) {}
# end
面向对象方式(一般不用,了解即可):
8、多线程
1)计算密集型多线程无用,如下示例:
import threading
v1 = [11,22,33] # +1
v2 = [44,55,66] # +100 def func(data,plus):
for i in range(len(data)):
data[i] = data[i] + plus t1 = threading.Thread(target=func,args=(v1,1))
t1.start() t2 = threading.Thread(target=func,args=(v2,100))
t2.start()
2)IO操作,多线程有用(IO操作不占用cpu),如“三、线程和进程”中创建多个线程的代码示例;
9、多线程的问题(加锁+释放锁)
import time
import threading lock = threading.RLock() n = 10 def task(i):
print('这段代码不加锁',i) lock.acquire() # 加锁,此区域的代码同一时刻只能有一个线程执行
global n
print('当前线程',i,'读取到的n值为:',n)
n = i
time.sleep(1)
print('当前线程',i,'修改n值为:',n)
lock.release() # 释放锁 for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
总结:
1. 应用程序/进程/线程的关系? *****(面试题:进程/线程/协程的区别?)
2. 为什么要创建线程?
由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。
注意:线程是为了工作。
3. 为什么要创建进程?
进程和进程之间做数据隔离(Java/C#)。
注意:进程是为了提供环境让线程工作。
4. Python
a. Python中存在一个GIL锁 *****
- 造成:多线程无法利用多核优势。
- 解决:开多进程处理(浪费资源)
进程和线程的使用准则:
IO密集型:多线程
计算密集型:多进程
b. 线程的创建
- Thread *****
- MyThread
c. 其他
- join *****
- setDaemon *****
- setName *****
- threading.current_thread() *****
d. 锁
- 获得
- 释放
操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁的更多相关文章
- python中socket、进程、线程、协程、池的创建方式和应用场景
进程 场景 利用多核.高计算型的程序.启动数量有限 进程是计算机中最小的资源分配单位 进程和线程是包含关系 每个进程中都至少有一条线程 可以利用多核,数据隔离 创建 销毁 切换 时间开销都比较大 随着 ...
- python中多进程multiprocessing、多线程threading、线程池threadpool
浅显点理解:进程就是一个程序,里面的线程就是用来干活的,,,进程大,线程小 一.多线程threading 简单的单线程和多线程运行:一个参数时,后面要加逗号 步骤:for循环,相当于多个线程——t=t ...
- Python之路,Day9, 进程、线程、协程篇
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
- Python学习之路--进程,线程,协程
进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Q ...
- python中的进程、线程(threading、multiprocessing、Queue、subprocess)
Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...
- python 学习笔记八 进程和线程 (进阶篇)
什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执 ...
- Python 中的进程、线程、协程、同步、异步、回调
进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说 ...
- Python学习笔记 - day13 - 进程与线程
概述 我们都知道windows是支持多任务的操作系统. 什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务.打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多 ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- python(40)- 进程、线程、协程及IO模型
一.操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式:向下管理硬件,向上提供接口. 操作系统进行进程切换:1.出现IO操作:2.固定时间. 固定时间很短,人感受不到.每一个应用层运行起 ...
随机推荐
- Titel Block不显示
在原有原理图上New page时不显示Titel Block 解决办法:两种(1)(2) 方法1.在新建的原理图上右键选择Schematic Page Properties,按下图勾选即可 方法2.进 ...
- C++ 内存泄漏
1. 内存泄漏: 在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况. 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前 ...
- nyoj 1129 Salvation
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1129 题目分析:感觉题目说的不是多么的清晰,看了别人的分析觉得,也就是说在一个方向不能拐 ...
- iOS开发多线程篇 09 —NSOperation简单介绍
iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...
- spring+redis+nginx 实现分布式session共享
1,spring 必须是4.3以上版本的 2,maven配置 添加两个重要的依赖 <dependency> <groupId>org.springframework.sessi ...
- mysql 索引优化,索引建立原则和不走索引的原因
第一:选择唯一性索引 唯一性索引的值是唯一的,可以更快捷的通过该索引来确定某条记录. 2.索引的列为where 后面经常作为条件的字段建立索引 如果某个字段经常作为查询条件,而且又有较少的重复列或者是 ...
- Linux 比较重要且难掌握命令 集合
1. find find path –option [-print] [-exec command] {} \; find . -maxdepth 1 -name aa find . -maxdept ...
- Servlet 表单数据
很多情况下,需要传递一些信息,从浏览器到 Web 服务器,最终到后台程序.浏览器使用两种方法可将这些信息传递到 Web 服务器,分别为 GET 方法和 POST 方法. GET 方法 GET 方法向页 ...
- 从获取点击事件根元素谈 target和currentTarget
事情由来: 写了一个点击事件,想获取根元素,想的直接用current就行了,因为之前就是这么用的,但是之前的点击元素是没子元素的,current就是根元素,但是这次点击元素内部有子元素,current ...
- -webkit-transition: all .2s ease-in-out;
W3C标准中对CSS3的transition这是样描述的:CSS的transition允许CSS的属性值在一定的时间区间内平滑地过渡.这种效果可以在鼠标单击.获得焦点.被点击或对元素任何改变中触发,并 ...