📜  并发与并行

📅  最后修改于: 2020-11-08 08:41:09             🧑  作者: Mango


并发性和并行性都用于多线程程序,但是它们之间的相似性和区别存在很多混淆。在这方面的一个大问题:并发并行性与否?尽管这两个术语看起来非常相似,但是对以上问题的回答是“否”,但并发性和并行性并不相同。现在,如果它们不相同,那么它们之间的基本区别是什么?

简而言之,并发处理从不同线程管理对共享状态的访问,另一方面,并行处理利用多个CPU或其内核来提高硬件性能。

详细并发

并发是两个任务在执行中重叠时。可能是应用程序同时在多个任务上进行的情况。我们可以用图解的方式理解它;多个任务正在同时取得进展,如下所示-

并发

并发级别

在本节中,我们将在编程方面讨论三个重要的并发级别-

低级并发

在这种并发级别,显式使用原子操作。我们不能使用这种并发来构建应用程序,因为它很容易出错并且很难调试。甚至Python也不支持这种并发。

中级并发

在这种并发中,不使用显式原子操作。它使用显式锁。 Python和其他编程语言支持此类并发。通常,应用程序程序员使用此并发。

高级并发

在这种并发中,既不使用显式的原子操作也不使用显式的锁。 Python具有并发模块模块来支持这种并发性。

并发系统的属性

为了使程序或并发系统正确,必须满足某些属性。与系统终止有关的属性如下-

正确性

正确性属性意味着程序或系统必须提供所需的正确答案。为了简单起见,我们可以说系统必须正确地将启动程序状态映射到最终状态。

安全性

安全属性意味着程序或系统必须保持“良好”“安全”状态,并且绝不做任何“不良”操作

活力财产

此属性意味着程序或系统必须“取得进展” ,并且它将达到某些理想的状态。

并发系统的参与者

这是并发系统的一个共同属性,其中可以有多个进程和线程,它们同时运行以在各自的任务上取得进展。这些进程和线程称为并发系统的参与者。

并发系统资源

参与者必须利用内存,磁盘,打印机等资源才能执行任务。

某些规则

每个并发系统都必须具有一组规则,以定义参与者要执行的任务的种类以及每个参与者的时间安排。这些任务可能是获取锁,共享内存,修改状态等。

并发系统的障碍

在实施并发系统时,程序员必须考虑以下两个重要问题,这可能是并发系统的障碍-

数据共享

实现并发系统时的一个重要问题是多个线程或进程之间的数据共享。实际上,程序员必须确保锁保护共享数据,以便对它的所有访问都被序列化,并且一次只能有一个线程或进程可以访问共享数据。如果多个线程或进程都试图访问相同的共享数据,则除了其中至少一个线程外,其他所有线程或进程都不会被阻塞并保持空闲状态。换句话说,我们可以说,在强制执行锁定时,我们一次只能使用一个进程或线程。可以有一些简单的解决方案来消除上述障碍-

数据共享限制

最简单的解决方案是不共享任何可变数据。在这种情况下,我们不必使用显式锁定,并且可以解决由于相互数据导致的并发障碍。

数据结构协助

很多时候,并发进程需要同时访问相同的数据。除了使用显式锁之外,另一种解决方案是使用支持并发访问的数据结构。例如,我们可以使用提供线程安全队列的队列模块。我们还可以将multiprocessing.JoinableQueue类用于基于多处理的并发。

不变的数据传输

有时,我们使用的数据结构(例如并发队列)不合适,那么我们可以传递不可变数据而无需锁定它。

可变数据传输

继续上述解决方案,假设如果只需要传递可变数据,而不是不可变数据,那么我们可以传递只读的可变数据。

共享I / O资源

实现并发系统的另一个重要问题是线程或进程对I / O资源的使用。当一个线程或进程使用I / O的时间如此长,而另一个线程或进程处于空闲状态时,就会出现问题。在使用I / O繁重的应用程序时,我们可以看到这种障碍。可以借助一个示例来理解,即从Web浏览器请求页面。这是一个繁重的应用程序。在这里,如果请求数据的速率比消耗数据的速率慢,那么我们的并发系统中将存在I / O障碍。

以下Python脚本用于请求网页并获取网络获取所请求页面所花费的时间-

import urllib.request

import time

ts = time.time()

req = urllib.request.urlopen('http://www.tutorialspoint.com')

pageHtml = req.read()

te = time.time()

print("Page Fetching Time : {} Seconds".format (te-ts))

执行完上述脚本后,我们可以获得页面获取时间,如下所示。

输出

Page Fetching Time: 1.0991398811340332 Seconds

我们可以看到,获取页面的时间超过一秒钟。现在,如果我们想获取成千上万个不同的网页,您将了解我们的网络将花费多少时间。

什么是并行性?

并行性可以定义为将任务拆分为可以同时处理的子任务的技术。如上所述,与并发相反,在并发中同时发生两个或更多事件。我们可以用图解的方式理解它;一个任务分为多个可以并行处理的子任务,如下所示:

平行性

为了更了解并发和并行性之间的区别,请考虑以下几点:

并发但不并行

一个应用程序可以是并发的,但不能是并行的,这意味着它可以同时处理多个任务,但这些任务不会分解为子任务。

并行但非并行

一个应用程序可以是并行的,但不能是并发的,这意味着它一次只能处理一个任务,分解为子任务的任务可以并行处理。

并行或并发

一个应用程序不能是并行的或并发的。这意味着它一次只能处理一个任务,并且该任务永远不会分解为子任务。

并行和并发

一个应用程序可以是并行的,也可以是并发的,这意味着它既可以同时处理多个任务,又可以分解为多个子任务以并行执行。

并行性的必要性

我们可以通过在单个CPU的不同内核之间或在网络内连接的多台计算机之间分配子任务来实现并行性。

考虑以下重要点,以了解为什么必须实现并行性-

高效的代码执行

借助并行性,我们可以高效地运行代码。这将节省我们的时间,因为部分中的相同代码可以并行运行。

比顺序计算更快

顺序计算受物理和实际因素的限制,因此无法获得更快的计算结果。另一方面,此问题可以通过并行计算解决,并且与顺序计算相比,可以为我们提供更快的计算结果。

减少执行时间

并行处理减少了程序代码的执行时间。

如果我们谈论现实生活中的并行性示例,那么计算机图形卡就是强调并行处理真正力量的示例,因为它具有数百个独立工作的内核,这些内核可以独立工作并可以同时执行。由于这个原因,我们也能够运行高端应用程序和游戏。

了解要实施的处理器

我们了解并发性,并行性以及它们之间的区别,但是有关实现它的系统又如何呢?了解我们将要在其上实施的系统非常必要,因为它使我们受益于在设计软件时做出明智的决定。我们有以下两种处理器-

单核处理器

单核处理器能够在任何给定时间执行一个线程。这些处理器使用上下文切换来在特定时间存储线程的所有必要信息,然后在以后恢复信息。上下文切换机制可帮助我们在给定的每秒内在多个线程上取得进展,并且看起来系统正在处理多个事情。

单核处理器具有许多优势。这些处理器需要较少的功率,并且多个内核之间没有复杂的通信协议。另一方面,单核处理器的速度受到限制,不适用于大型应用。

多核处理器

多核处理器具有多个独立的处理单元,也称为

这样的处理器不需要上下文切换机制,因为每个内核都包含执行一系列存储指令所需的所有内容。

提取-解码-执行周期

多核处理器的核心遵循一个执行周期。该循环称为“获取-解码-执行”循环。它涉及以下步骤-

这是循环的第一步,其中涉及从程序存储器中获取指令。

解码

最近获取的指令将被转换为一系列信号,这些信号将触发CPU的其他部分。

执行

这是将执行已提取和已解码指令的最后一步。执行结果将存储在CPU寄存器中。

此处的一个优点是,多核处理器中的执行速度比单核处理器中的执行速度快。适用于大型应用。另一方面,多个核之间的复杂通信协议是一个问题。与单核处理器相比,多核需要更多的电源。