我试图理解多处理相对于线程的优势。我知道多处理绕过了全局解释器锁,但是还有什么其他的优势,线程不能做同样的事情吗?
当前回答
进程可能有多个线程。这些线程可以共享内存,并且是进程中的执行单元。
进程运行在CPU上,因此线程驻留在每个进程之下。进程是独立运行的独立实体。如果您想在每个进程之间共享数据或状态,您可以使用内存存储工具,如缓存(redis, memcache),文件或数据库。
其他回答
线程共享相同的内存空间,以确保两个线程不共享相同的内存位置,因此必须采取特殊的预防措施。CPython解释器使用一种称为GIL的机制来处理这个问题,或全局解释器锁
什么是GIL(我只是想澄清GIL,上面重复了一次)?
在CPython中,全局解释器锁(GIL)是一个互斥锁,用于保护对Python对象的访问,防止多个线程同时执行Python字节码。这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。
对于主要问题,我们可以使用用例,如何进行比较?
1-线程的用例:在GUI程序中,线程可以用来使应用程序具有响应性。例如,在文本编辑程序中,一个线程可以负责记录用户输入,另一个线程可以负责显示文本,第三个线程可以进行拼写检查,等等。在这里,程序必须等待用户交互。这是最大的瓶颈。线程的另一个用例是受IO限制或受网络限制的程序,例如web scraper。
2- Multiprocessing的用例:当程序是CPU密集型的,并且不需要做任何IO或用户交互的情况下,Multiprocessing优于线程。
要了解更多详细信息,请访问此链接和链接,或者您需要深入了解线程访问这里,多处理访问这里
多处理
Multiprocessing通过增加cpu来提高计算能力。 多个进程同时执行。 创建流程既耗时又耗费资源。 多处理可以是对称的也可以是非对称的。
Python中的多处理库使用独立的内存空间,多个CPU核心,绕过CPython中的GIL限制,子进程是可杀死的(例如程序中的函数调用),并且更容易使用。 该模块的一些注意事项是内存占用较大,IPC稍微复杂一些,开销更大。
多线程
多线程创建单个进程的多个线程,以提高计算能力。 一个进程的多个线程并发执行。 线程的创建在时间和资源上都是经济的。
多线程库是轻量级的,共享内存,负责响应式UI,并用于I/O绑定应用程序。 该模块不可杀死,并受GIL约束。 多个线程生活在同一个进程中的同一个空间中,每个线程将执行特定的任务,有自己的代码,自己的堆栈内存,指令指针,并共享堆内存。 如果一个线程有内存泄漏,它会损害其他线程和父进程。
使用Python的多线程和多处理示例
Python 3有启动并行任务的功能。这使我们的工作更容易。
它有线程池和进程池。
下面让我们来了解一下:
ThreadPoolExecutor例子
import concurrent.futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# Start the load operations and mark each future with its URL
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
print('%r generated an exception: %s' % (url, exc))
else:
print('%r page is %d bytes' % (url, len(data)))
ProcessPoolExecutor
import concurrent.futures
import math
PRIMES = [
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
def is_prime(n):
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def main():
with concurrent.futures.ProcessPoolExecutor() as executor:
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d is prime: %s' % (number, prime))
if __name__ == '__main__':
main()
进程可能有多个线程。这些线程可以共享内存,并且是进程中的执行单元。
进程运行在CPU上,因此线程驻留在每个进程之下。进程是独立运行的独立实体。如果您想在每个进程之间共享数据或状态,您可以使用内存存储工具,如缓存(redis, memcache),文件或数据库。
关键的优势是隔离。进程崩溃不会导致其他进程崩溃,而线程崩溃可能会对其他线程造成严重破坏。
线程模块使用线程,多处理模块使用进程。不同之处在于线程在相同的内存空间中运行,而进程有单独的内存。这使得在多进程之间共享对象变得有点困难。由于线程使用相同的内存,必须采取预防措施,否则两个线程将同时写入同一内存。这就是全局解释器锁的作用。
生成进程比生成线程要慢一些。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 自动化invokerrequired代码模式
- 解析日期字符串并更改格式
- 使用try和。Python中的if