文档章节

Python 并发部分的面试题

o
 osc_f85py9gf
发布于 2019/05/14 09:45
字数 3346
阅读 22
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

<h2 id="toc_0">进程</h2>

<ul> <li>进程间内存是否共享?如何实现通讯?<br/> 进程间内存不共享,可以通过 <ol> <li>Manage模块加锁 </li> <li>通过队列或 </li> <li>通过管道加锁 </li> <li>socket实现通讯</li> </ol></li> <li>请聊聊进程队列的特点和实现原理? <ol> <li>先进先出 Queue</li> <li>后进先出 LifoQueue</li> <li>优先级队列 PriorityQueue</li> <li>线程本身带锁通过put()数据和get()数据,同一时间只有一个线程运行修改任务实现数据安全</li> </ol></li> <li>请画出进程的三状态转换图</li> </ul>

<pre class="line-numbers"><code class="language-python"> 就绪====运行 \阻塞/ </code></pre>

<ul> <li>你了解生产者模型消费者模型么?如何实现?</li> </ul>

<pre class="line-numbers"><code class="language-python">yield: def consumer(): n = yield n = yield n = yield n = yield n = yield n = yield n = yield n = yield def producer(): g = consumer() next(g) for i in range(2000000): g.send(i) </code></pre>

<ul> <li>从你的角度说说进程在计算机中扮演什么角色?<br/> 进程在计算机中扮演数据集的调用调配角色。<br/> 负责回收和控制子线程的运行,是一个数据集。<br/> ##线程</li> <li>GIL锁是怎么回事?<br/> GIL锁是全局解释器锁,只有CPython中使用,同一时间只能有一个线程调度CPU</li> <li>在python中是否线程安全?<br/> 不安全,需要加锁才安全</li> <li>什么叫死锁?<br/> 同时满足两个条件锁才能解开,分别有两把或以上的锁,有多个线程分别抢占了两个条件中的锁,互不释放造成阻塞,死锁现象。</li> <li>logging模块是否是线程安全的?<br/> logging模块是线程安全的,因为使用的是单例设计模式。</li> <li>threading.local的作用?<br/> Python提供了 threading.local 类,将这个类实例化得到一个全局对象,<br/> 但是不同的线程使用这个对象存储的数据其它线程不可见(本质上就是不同的线程使用这个对象时为其创建一个独立的字典)。</li> <li>程序从flaga执行到falgb的时间大致是多少秒?<br/> 60s 因为没有设置守护线程,需要等子线程跑完主线程才结束</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait, daemon=False) t.start() # flag b </code></pre>

<ul> <li>程序从flaga执行到falgb的时间大致是多少秒?<br/> 0.01s 因为设置守护线程,子线程等待所有非子线程结束子线程结束。</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait, daemon=True) t.start() # flag b </code></pre>

<ul> <li>程序从flaga执行到falgb的时间大致是多少秒?<br/> 60s 因为设置了阻塞需要等待子线程结束主线程才能结束</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait, daemon=True) t.start() t.join() # flag b </code></pre>

<ul> <li>读程序,请确认执行到最后number是否一定为0<br/> 不一定,因为存在线程安全问题,同一时间修改变量值</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading loop = int(1E7) def _add(loop: int = 1): global number for _ in range(loop): number += 1 def _sub(loop: int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add, args=(loop,)) ts = threading.Thread(target=_sub, args=(loop,)) ta.start() ts.start() ta.join() ts.join() print(number) </code></pre>

<ul> <li>读程序,请确认执行到最后number是否一定为0<br/> 一定为0 ,因为增删操作只有一条语句不会产生数据安全问题。</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading loop = int(1E7) def _add(loop: int = 1): global number for _ in range(loop): number += 1 def _sub(loop: int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add, args=(loop,)) ts = threading.Thread(target=_sub, args=(loop,)) ta.start() ta.join() ts.start() ts.join() print(number) </code></pre>

<ul> <li>读程序,请确认执行到最后number的长度是否一定为1<br/> 不一定为1,因为产生了阻塞可能有数据安全问题。</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading loop = int(1E7) def _add(loop: int = 1): global numbers for _ in range(loop): numbers.append(0) def _sub(loop: int = 1): global number while not numbers: time.sleep(1E-8) numbers.pop() numbers = [0] ta = threading.Thread(target=_add, args=(loop,)) ts = threading.Thread(target=_sub, args=(loop,)) ta.start() ta.join() ts.start() ts.join() print(numbers) </code></pre>

<ul> <li>读程序,请确认执行到最后number的长度是否一定为1<br/> 不一定为1,因为产生了阻塞可能有数据安全问题。</li> </ul>

<pre class="line-numbers"><code class="language-python">import threading loop = int(1E7) def _add(loop: int = 1): global numbers for _ in range(loop): numbers.append(0) def _sub(loop: int = 1): global number while not numbers: time.sleep(1E-8) numbers.pop() numbers = [0] ta = threading.Thread(target=_add, args=(loop,)) ts = threading.Thread(target=_sub, args=(loop,)) ta.start() ts.start() ta.join() ts.join() print(numbers) </code></pre>

<h1 id="toc_1">协程</h1>

<ul> <li>什么是协程?常用的协程模块有哪些?<br/> 在线程遇到阻塞的情况时切换到另一个线程继续执行,如果遇到阻塞再到另一个线程执行。如果跳转过的线程转为就绪状态就直接执行,<br/> 知道程序中没有阻塞。有gevent,和greenlet.</li> <li>协程中的join是用来做什么用的?它是如何发挥作用的?<br/> 协程是遇到阻塞才切换,join负责阻塞开始执行程序。</li> <li>使用协程实现并发的tcp</li> </ul>

<pre class="line-numbers"><code class="language-python">server端 from gevent import monkey;monkey.patch_all() import gevent import time import random import socket sk = socket.socket() server_addr = (&#39;127.0.0.1&#39;,9988) sk.bind(server_addr) sk.listen() def listen(conn): while True: msg = conn.recv(1024).decode(&#39;utf-8&#39;) if msg == &#39;q&#39;:break conn.send(msg.upper().encode(&#39;utf-8&#39;)) if __name__ == &#39;__main__&#39;: while True: conn,addr = sk.accept() gevent.spawn(listen,conn) </code></pre>

<ul> <li>在一个列表中有多个url,请使用协程访问所有url,将对应的网页内容写入文件保存</li> </ul>

<pre class="line-numbers"><code class="language-python">from gevent import monkey;monkey.patch_all() import time import random import gevent from urllib.request import urlopen url_dic = { &#39;协程&#39;:&#39;http://www.cnblogs.com/Eva-J/articles/8324673.html&#39;, &#39;线程&#39;:&#39;http://www.cnblogs.com/Eva-J/articles/8306047.html&#39;, &#39;目录&#39;:&#39;https://www.cnblogs.com/Eva-J/p/7277026.html&#39;, &#39;百度&#39;:&#39;http://www.baidu.com&#39;, &#39;sogou&#39;:&#39;http://www.sogou.com&#39;, &#39;4399&#39;:&#39;http://www.4399.com&#39;, &#39;豆瓣&#39;:&#39;http://www.douban.com&#39;, &#39;sina&#39;:&#39;http://www.sina.com.cn&#39;, &#39;淘宝&#39;:&#39;http://www.taobao.com&#39;, &#39;JD&#39;:&#39;http://www.JD.com&#39; } def getHtml(url): ret = urlopen(url) html = ret.read() html_file = url.replace(&#39;.&#39;,&#39;_&#39;).lstrip(&#39;https://&#39;).replace(&#39;/&#39;,&#39;_&#39;)+&#39;.html&#39; with open(html_file,mode=&#39;wb&#39;) as f: f.write(html) print(url+&#39;done&#39;) if __name__ == &#39;__main__&#39;: print(&#39;start&#39;) lst = list() for url in url_dic: ret = gevent.spawn(getHtml,url_dic[url]) lst.append(ret) for url in lst: url.join() print(1) </code></pre>

<h1 id="toc_2">综合</h1>

<ul> <li>进程和线程的区别<br/> 进程是计算机资源分配的最小单位,线程是cpu调度的最小单位,线程较进程来说较轻量,启动更迅速。调用更方便</li> <li>进程池、线程池的优势和特点<br/> 进程池一般在高计算的条件下使用,资源消耗更多。<br/> 线程池可以运行在一个进程中,执行效率更高,可控cpu使用率。节约资源。</li> <li>线程和协程的异同?<br/> 协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。<br/> 协程实际上是在一个线程中,只不过每个协程对CUP进行分时,协程可以访问和使用unity的所有方法和component<br/> 线程,多线程是阻塞式的,每个IO都必须开启一个新的线程,但是对于多CPU的系统应该使用thread,尤其是有大量数据运算的时刻,<br/> 但是IO密集型就不适合;而且thread中不能操作unity的很多方法和component</li> <li>请简述一下互斥锁和递归锁的异同?<br/> 两者在在单锁的情况下都可以保证数据的可靠性。<br/> 二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁。</li> <li>请列举一个python中数据安全的数据类型?<br/> Queue</li> <li>Python中如何使用线程池和进程池</li> </ul>

<pre class="line-numbers"><code class="language-python">from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ProcessPoolExector p = ProcessPoolExector(4) ret = p.submit(func,aa) print(ret.result()) </code></pre>

<ul> <li>简述<br/> 进程、线程、协程的区别<br/> 进程是:一个CPU情况下,多个程序分别使用机器资源(CPU或硬盘等)的概念;<br/> 线程是:一个进程情况下,多个执行流程(即线程)分别使用分配给该进程的机器资源的概念; <ul> <li>协程是:一个线程情况下,多个执行流程(即协程)由线程控制,分别使用分配给该线程的机器资源的概念;<br/> 以及应用场景?</li> <li>多进程:密集CPU任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程。 multiprocessing<br/> 缺陷:多个进程之间通信成本高,切换开销大。</li> <li>多线程:密集I/O任务(网络I/O,磁盘I/O,数据库I/O)使用多线程合适。<br/> threading.Thread、multiprocessing.dummy<br/> 缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发。</li> <li>多线程请求返回是无序的,那个线程有数据返回就处理那个线程,而协程返回的数据是有序的。<br/> 缺陷:单线程执行,处理密集CPU和本地磁盘IO的时候,性能较低。处理网络I/O性能还是比较高.</li> </ul></li> <li>什么是并行,什么是并发?<br/> 并行是同一时间在多个cpu上同时执行多个程序<br/> 并发是同一时间在同一个cpu上在不同程序之间切换运行</li> <li>请解释同步和异步这两个概念?<br/> 同步执行程序需要等待结果<br/> 异步执行程序不需要等待结果</li> <li>请谈谈对异步非阻塞的了解?<br/> 执行效率高,可以实现高并发的应用场景</li> <li>简述信号量的实现原理 <ul> <li>信号量机制即利用pv操作来对信号量进行处理。什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;</li> <li>当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。一般来说,信号量S³0时,</li> <li>S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S&lt;0时,表示已经没有可用资源,</li> <li>请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S£0,</li> <li>表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。</li> </ul></li> <li>程序中的阻塞有哪些?给程序带来了哪些影响?<br/> input,sleep,io 程序会等待阻塞完成才会进入就绪队列,影响程序运行效率</li> <li>请分别用多进程、多线程、协程实现生产者消费者模型?</li> </ul>

<h1 id="toc_3">多进程</h1>

<pre class="line-numbers"><code class="language-python">import time import random from multiprocessing import Process,Queue def producer(name,que): for i in range(10): time.sleep(random.random()) food = &#39;便便💩&#39; print(&#39;%s 生产了一陀%s&#39; % (name,food)) que.put(food) def consumer(name,que): while True: time.sleep(random.random()) food = que.get() if not food: break print(&#39;%s 吃了一陀%s&#39; % (name,food)) if __name__ == &#39;__main__&#39;: p_l = list() que = Queue() p = Process(target=producer,args=(&#39;baoyuan&#39;,que)) p.start() p.join() c = Process(target=consumer,args=(&#39;alex&#39;,que,)) c.start() que.put(None) c.join() print(&#39;全部吃完啦。&#39;) </code></pre>

<h1 id="toc_4">多线程</h1>

<pre class="line-numbers"><code class="language-python">import time import random from queue import Queue from threading import Thread def producer(name,que): for i in range(10): time.sleep(random.random()) food = &#39;便便💩&#39; print(&#39;%s 生产了一陀%s&#39; % (name,food)) que.put(food) def consumer(name,que): while True: time.sleep(random.random()) food = que.get() if not food: break print(&#39;%s 吃了一陀%s&#39; % (name,food)) if __name__ == &#39;__main__&#39;: p_l = list() que = Queue() p = Thread(target=producer,args=(&#39;baoyuan&#39;,que)) p.start() p.join() c = Thread(target=consumer,args=(&#39;alex&#39;,que,)) c.start() que.put(None) c.join() print(&#39;全部吃完啦。&#39;) </code></pre>

<h1 id="toc_5">协程</h1>

<pre class="line-numbers"><code class="language-python">from gevent import monkey;monkey.patch_all() from queue import Queue import gevent import random import time def producer(name,que): for i in range(10): time.sleep(random.random()) food = &#39;便便💩&#39; print(&#39;%s 生产了一陀%s&#39; % (name,food)) que.put(food) def consumer(name,que): while True: time.sleep(random.random()) food = que.get() if not food: break print(&#39;%s 吃了一陀%s&#39; % (name,food)) if __name__ == &#39;__main__&#39;: p_l = list() que = Queue() p = gevent.spawn(producer,&#39;baoyuan&#39;,que) p.join() c = gevent.spawn(consumer,&#39;alex&#39;,que) que.put(None) c.join() print(&#39;全部吃完啦。&#39;) </code></pre>

上一篇: Python 大文件处理
下一篇: Vim 简易配置
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4K
3
首列固定的列表

实现特殊的表格(UITableView)效果:即表格中的首列固定不动,而每一行除了首列均可左右拖动,以展现每一行更多内容。 作者谭林江(@无法越狱的痛)说:去益盟面试回来,感觉聊得有点郁闷,...

匿名
2013/01/24
1.2K
0
WSGI Web服务器--UV-Web

uv-web是一个轻量级的支持高并发的WSGI Web服务器,基于libuv构建,部分代码源于开源项目bjoern,本质是python的C扩展,所以适用于部署绝大部分 python web应用(如 Django) 特性 兼容 HTTP 1...

Jone.x
2013/03/04
1.7K
0
django-c10k-demo

这是一个演示程序,用来实现同时 10000 个并发连接到 Django 。涉及的概念包括:the C10k problem, the WebSocket protocol, the Django web framework, and Python's upcoming asynchronou......

匿名
2013/03/27
1.7K
0

没有更多内容

加载失败,请刷新页面

加载更多

认识Node

什么是Node? Node 是 JavaScript 的一种运行环境。可以使 JS 代码不依赖浏览器也可以执行。他俩的差异如下: 两个运行环境都包含了 ECMScript 。另一方面 JavaScript 包含了 BOM 和 DOM。 ...

长臂猿猴
27分钟前
13
0
正则表达式中的非捕获组是什么? - What is a non-capturing group in regular expressions?

问题: 非捕获组(即(?:) )如何在正则表达式中使用,它们有什么用? 解决方案: 参考一: https://stackoom.com/question/Ejkl/正则表达式中的非捕获组是什么 参考二: https://oldbug.net...

技术盛宴
28分钟前
6
0
他在国外演讲时说,学Python只要看答案做完这几十道题,就足够了

你想学Python?其实很简单,因为Python本身就是一门比较简单的编程语言。 你要做的也就是看着答案做完这几十道题就可以了,不管你是不是有编程基础,因为答案摆在那儿,你不可能不会做。 为什...

python小天
28分钟前
0
0
「2020最新」Spring最易学习教程 4—整合Mybatis 事务控制

0 复习 代理模式 代理模式,可以为目标类添加额外功能。 Spring 动态代理 定义目标类对象 定义额外功能,增强。实现Spring内置的接口 配置增强类 定义切入点 编织组装 增强类型 前置增强 Me...

鹿老师的Java笔记
48分钟前
21
0
OpenCV开发笔记(六十九):红胖子8分钟带你使用传统方法识别已知物体(图文并茂+浅显易懂+程序源码)

若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:h...

红模仿_红胖子
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部