Python之路PythonThread,第四篇,进程4
python3 进程/线程4
进程间同步互斥方法:
from multiprocessing import Lock
创建 进程锁对象
lock = Lock()
lock.acquire() 给临界区上锁
lock.release() 给临界区解锁
说明:1,具体实现上 acquire() 为一个条件阻塞函数;
2,当有任意一个进程先进行了acquire操作后,其他进程再企图进行acquire操作时就会阻塞,直到lock对象被release后其他进程CIA可以进行下次
acquire操作;
with lock: 也可以实现加锁,解锁
线程:
1,线程也可以使用计算机的多核资源,也是多任务编程方式之一;
2, 线程又称为轻量级的进程,在并发上和进程相同,但是在创建时销毁资源少;
说明:1,一个进程中可以包含多个线程,这个多个线程共享进程的资源;
2, 多个线程因为共享进程的资源,所以在通信上往往采用全局变量的方式;
3,线程也有自己特有的资源,比如TTD指令集等;
多进程和多线程的区别和联系:
1,多进程和多线程都是多任务编程方式,都可以使用计算机多核;
2,进程的创建要比线程消耗更多的资源;
3,进程的空间独立数据更安全,有专门的进程间通信方式进行交互;
4,一个进程包含多个线程,所以线程共享进程资源,没有专门的通信方式,依赖全局变量进行通信。 往往需要使用同步互斥机制,逻辑需要考虑更多;
5,进程线程都有自己特有的资源,多个关联任务的时候使用多线程资源消耗更少; 如果是多个无关联任务也不适用全部都使用线程;
from multiprocessing import Process,Lock
import time,sys def worker1(stream):
lock.acquire() # 加锁
for i in range(5):
time.sleep(1)
stream.write("Lock acquired via\n")
lock.release()#解锁 def worker2(stream):
# lock.acquire()
with lock: #加锁 语句块结束即解锁
for i in range(5):
time.sleep(1)
stream.write("Lock acquired directly\n")
# lock.release() lock = Lock()
#sys.stdout为所有进程都拥有的资源
w1 = Process(target=worker1,args=(sys.stdout,))
w2 = Process(target=worker2,args=(sys.stdout,)) w1.start()
w2.start() w1.join()
w2.join()
创建线程:
import threading
创建线程函数
threading.Tread()
功能:创建线程
参数:target 线程函数
args 以元组方式给线程函数传参
kwargs 以字典方式给线程函数传参
name 线程名称(默认Thread-1)
返回值:返回线程对象
线程属性和方法:
t.start() 启动一个线程
t.is_alive() 查看一个线程的状态
t.name 查看线程的名称
t.join([esc]) 阻塞等待回收线程
import threading
from time import ctime,sleep a = 10 def music(sec):
print("Listening music")
global a
a = 1000
sleep(sec) t = threading.Thread(name = "my thread",\
target = music,args = (2,)) t.start()
print("创建线程")
sleep(3)
print(a)
deamon属性:
1,设置该属性默认为False, 主线程执行完毕后不会影响其他线程的执行;
2, 如果设置为True, 则主线程执行完毕其他线程也终止执行;
代码:
设置daemon: t.setDaemon(True) 或 t.daemon = True
获取daemon属性值: t.isDaemon()
import threading
from time import sleep,ctime def fun():
print("This is a thread test")
sleep(5)
print("thread over") t = threading.Thread(name = 'levi',\
target = fun) # t.setDaemon(True)
t.daemon = True
print(t.isDaemon()) t.start() print(t.is_alive()) #线程状态
print(t.name) #线程名称 t.join(2) print("all over",ctime())
线程间的通信:
全局变量进行通信;
线程间的同步和互斥;
import threading
from time import sleep s = None e = threading.Event() def bar():
print("呼叫foo")
global s
s = "天王盖地虎" def foo():
print('foo等口令')
sleep(2)
print('foo收到 %s'%s)
e.set() def fun():
sleep(1)
e.wait()
print("内奸出现")
global s
s = "小鸡炖蘑菇" t1 = threading.Thread\
(name = 'bar',target = bar) t2 = threading.Thread\
(name = 'foo',target = foo) t3 = threading.Thread\
(name = 'fun',target = fun) t1.start()
t2.start()
t3.start() t1.join()
t2.join()
t3.join()
线程 event:
创建事件对象: e = threading.Event()
e.wait([timeout]) 如果e被设置则不会阻塞,未被设置则阻塞 ;timeout为阻塞的超时时间;
e.set() 将e变为设置是状态
e.clear() 将e变为未设置状态;
from threading import *
import random
from time import sleep a = 500 #创建事件对象
e = Event() #子线程不断减少a 但是希望a的值不会少于100
def fun():
global a
while True:
sleep(2)
print('a = ',a)
e.wait()
a -= random.randint(0,100) t = Thread(target = fun)
t.start() #主线程不断的让a增加以确保a不会小于100
while True:
sleep(1)
a += random.randint(1,10)
if a > 100:
e.set()
else:
e.clear() t.join()
线程锁:
lock = threading.Lock() 创建线程锁;
lock.acquire() 上锁
lock.release() 解锁
import threading a = b = 0 lock = threading.Lock() def value():
while True:
lock.acquire()
if a != b:
print("a = %d,b = %d"%(a,b))
lock.release() t = threading.Thread(target = value)
t.start() while True:
lock.acquire()
a += 1
b += 1
lock.release()
t.join()
创建自己的线程类:
1,自定义类 继承于 原有线程类Thread
2, 复写原有的run方法;
3,创建线程对象调用start的时候会自动执行run
from time import ctime,sleep
import threading #编写自己的线程类
class MyThread(threading.Thread):
def __init__(self,func,args,name = 'Levi'):
threading.Thread.__init__(self)
self.func = func
self.name = name
self.args = args #自定义 线程启动函数
def run(self):
self.func(*self.args) #待启动的线程函数
def player(file,time):
for i in range(2):
print('start playing %s:%s'\
%(file,ctime()))
sleep(time) t = MyThread(player,('baby.mp3',3)) t.start() t.join()
线程池第三方模块 :threadpool
sudo pip3 install threadpool
GIL (全局解释器锁)
python ---> 支持多线程 ----> 同步和互斥 ---> 加锁 --->超级锁 ---> 解释器在同一时刻只能解释一个线程;
大量python库为了省事依赖于这种机制----> python多线程效率低;
GIL 即为从python解释器由于 上锁带了的同一时刻只能解释一个线程的问题;
解决方案:
1, 不使用线程,转而使用进程;
2, 不使用c 作为解释器 java c# 都可以做python解释器;
(1)IO密集型: 程序中进行了大量的IO操作,只有少量的CPU操作;
在内存中进行了数据的交换的操作都可以认为是IO操作;
特点: 速度较慢,使用cpu不高;
(2)cpu密集型(计算密集型):大量的程序都在进行运算操作;
特点:cpu占有率高
效率测试:
Line cpu 1.224205732345581
Line IO 4.142379522323608
Thread cpu 0.7009162902832031
Thread IO 3.458016872406006
Process cpu 0.6419346332550049
Process IO 1.8482108116149902
总结:多线程的工作效率和单线程几乎相近,而多进程要比前两者有明显的效率提升
设计模式:
设计模式代表了一种最佳实践,是被开发人员长期开发总结,用来解决某一类问题的思路方法。这种方法保证了代码的效率,也易于理解;
单例模式,工厂模式,生产者模式。。。
生产者消费者模式:
高内聚: 在同一模块内,实现单一功能,尽量不使功能混杂;
低耦合: 不同的模块之间尽量相互独立,减少模块间的影响;
代码实现
from threading import Thread
#python标准库中的队列模块
import queue
import time #创建一个队列模型作为商品的仓库
q = queue.Queue() class Producer(Thread):
def run(self):
count = 0
while True:
if q.qsize() < 50:
for i in range(3):
count += 1
msg = "产品 %d"%count
q.put(msg) #将产品放入队列
time.sleep(1) class Customer(Thread):
def run(self):
while True:
if q.qsize() > 20:
for i in range(2):
msg = q.get() #从仓库拿到商品
print("消费了一个 %s"%msg)
time.sleep(1) #创建三个生产者
for i in range(3):
p = Producer()
p.start() #创建5个消费者
for i in range(5):
p = Customer()
p.start()
总结:
1,进程和线程的区别
2.会创建使用线程 threading
3.掌握基本的线程间同步互斥编程方法
4.知道什么是GIL
5.了解设计模式的概念
*************************************************************
面试问题:
1. 进程和线程的区别
2. 什么是同步和互斥
3. 给一个具体的情况,问采用进程还是线程为什么
4. 你是怎么处理僵尸进程的
5. 怎么测试一个硬盘的读写速度
6. xxx框架 是用的多进程还是多线程并发
7. 进程间通信方式知道哪些,都有什么特点
同步
互斥
Python之路PythonThread,第四篇,进程4的更多相关文章
- Python之路【第四篇】:模块
什么是模块: 模块就是一个功能的集合. 模块就和乐高积木差不多,你用这些模块组合出一个模型,然后也可以用这个模块加上其他的模块组合成一个新的模型 模块的种类: 1.内置模块(python自带的比如os ...
- Python之路PythonThread,第二篇,进程2
python3 进程2 僵尸进程处理方法: 3,创建二级子进程处理 4,在父进程中使用信号处理的方法忽略子进程发来的信号: signal(SIGCHLD,DIG,IGN) # 创建二级子进场解决僵 ...
- Python之路PythonThread,第一篇,进程1
python3 进程1 多任务编程: 可以有效的利用计算机资源,同时执行多个任务, 进程:进程就是程序在计算机中一次执行的结果: 进程和程序的区别: 程序是一个静态文件的描述,不占用计算机的系统资源: ...
- Python之路【第四篇】:Python基础之函数
函数的理解 面向过程:根据业务逻辑从上到下垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 函数作用是你的程序有良好的扩展性.复用性. 同样的功能要是用3次以上的话就建议使 ...
- Python之路【第四篇】: 函数、递归、内置函数
一. 背景提要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码 while True: i ...
- 【Python之路】第四篇--Python基础之函数
三元运算 三元运算(三目运算),是对简单的条件语句的缩写 # 书写格式 result = 值1 if 条件 else 值2 # 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2” ...
- Python之路【第四篇补充】:面向对象初识和总结回顾
面向过程的编程 面向过程:根据业务逻辑从上到下写垒代码! 例子: 需求一.有一个程序需要做身份认证: 用户名有个字典: #定义一个用户名信息字典 user_info = { "zhangsa ...
- Python之路【第四篇】Python基础2
一.格式化输出 按要求输出信息 name=input("name:") age=int(input("age:")) job=input("job:& ...
- Python之路,第四篇:Python入门与基础4
Python3 字符串 字符串是一个有序的字符序列 如何表示一个字符串: 在非注释中凡是用引号括起来的部分都是字符串: ‘ 单引号 ” 双引号 ‘’‘ 三单引号 “”“ ...
- Python之路(第二十四篇) 面向对象初级:多态、封装
一.多态 多态 多态:一类事物有多种形态,同一种事物的多种形态,动物分为鸡类,猪类.狗类 例子 import abc class H2o(metaclass=abc.ABCMeta): def _ ...
随机推荐
- php 循环数组问题
$a = array('abe','ben','cam'); //foreach遍历数组时,实际上是遍历的数组的一个拷贝,并且在开始遍历之前会把指针指向拷贝的开始:,根据cow机制,写时,重新复制一份 ...
- 【转】在使用实体框架(Entity Framework)的应用中加入审计信息(Audit trail)跟踪数据的变动
在一些比较重要的业务系统中,通常会要求系统跟踪数据记录的变动情况.系统要记录什么时间,什么人,对那些信息进行了变动. 比较简单的实现方式是在每个表中加入两个字段CreatedBy和CreatedAt, ...
- spring cloud jwt用户鉴权及服务鉴权
用户鉴权 客户端请求服务时,根据提交的token获取用户信息,看是否有用户信息及用户信息是否正确 服务鉴权 微服务中,一般有多个服务,服务与服务之间相互调用时,有的服务接口比较敏感,比如资金服务,不允 ...
- Win10系列:UWP界面布局进阶3
与以往的Windows操作系统不同,Windows 10操作系统在正式版当中取消了任务栏中的"开始"按钮,将大部分的应用程序图标放置在开始屏中,同时将系统设置等常用功能整合到了Ch ...
- Android 应用基础知识和应用组件
应用基础知识 安装到设备后,每个 Android 应用都运行在自己的安全沙箱内: Android 操作系统是一种多用户 Linux 系统,其中的每个应用都是一个不同的用户: 默认情况下,系统会为每个应 ...
- 深度学习----Xavier初始化方法
“Xavier”初始化方法是一种很有效的神经网络初始化方法,方法来源于2010年的一篇论文<Understanding the difficulty of training deep feedf ...
- 深入理解java虚拟机---java虚拟机的发展史(四)
1.java虚拟机 A:java虚拟机有很多个版本,但是我们经常使用的是sun公司的HotSpot,可以通过以下命令获取java虚拟机版本 B:JAVA虚拟机分类: 1.Sun Class VM 2. ...
- 2.6 C++通过引用来传递和返回类对象
参考:http://www.weixueyuan.net/view/6338.html 总结: C++语言中,由类声明的对象,和其它类型声明的变量一样,同样可以通过传值.引用和指针的方式作为函数的参数 ...
- linux下Mysql多实例实现
什么是MySQL多实例 MySQL多实例就是在一台机器上开启多个不同的服务端口(如:3306,3307),运行多个MySQL服务进程,通过不同的socket监听不同的服务端口来提供各自的服务:: My ...
- weblogic连接池过小导致TPS呈周期性跳坑现象
利用晚上时间跑个12小时稳定性,第二天发现TPS曲线图成了这个样子. 排查步骤: 1.观察TPS图发现,几乎每两个小时TPS掉一次坑,是周期性的,而且TPS有掉到0的现象.LR上也有失败的交易,猜想是 ...