Учебное пособие по многопоточности Python | Месяц темы Python

задняя часть Python Операционная система
Учебное пособие по многопоточности Python | Месяц темы Python

Эта статья участвует в "Месяце тем Python", подробнее см.Ссылка на мероприятие

В этом руководстве по многопоточности Python вы увидите различные способы создания потоков и научитесь реализовывать синхронизацию для потокобезопасных операций. Каждый раздел этого поста содержит пример и пример кода для пошагового объяснения концепции.

Между прочим, многопоточность — это основная концепция программирования, поддерживаемая почти всеми языками программирования высокого уровня. Итак, первое, что вы должны знать: что такое многопоточность и что означает многопоточность в информатике.

Что такое потоки в информатике?

В программировании программного обеспечения поток — это наименьшая единица выполнения с независимым набором инструкций. Он является частью процесса и выполняется в том же контексте, что и общие ресурсы программы, такие как память. Поток имеет начальную точку, порядок выполнения и результат. У него есть указатель инструкций, который содержит текущее состояние потока и управляет следующим порядком выполнения.

Что такое многопоточность в информатике?

Способность процесса выполнять несколько потоков параллельно называется многопоточностью. В идеале многопоточность может значительно повысить производительность любой программы. И механизм многопоточности Python очень удобен для пользователя, вы можете быстро научиться.

Преимущества многопоточности

  • Многопоточность может значительно увеличить скорость вычислений многопроцессорной или многоядерной системы, поскольку каждый процессор или ядро ​​одновременно обрабатывает отдельный поток.
  • Многопоточность позволяет программе оставаться отзывчивой, пока один поток ожидает ввода, а другой поток выполняет графический интерфейс. Это утверждение относится к многопроцессорным или однопроцессорным системам.
  • Все потоки процесса могут обращаться к его глобальным переменным. Если глобальная переменная изменяется в одном потоке, она также видна другим потокам. Потоки также могут иметь свои собственные локальные переменные.

Недостатки многопоточности

  • В однопроцессорной системе многопоточность не влияет на скорость вычислений. Производительность может снизиться из-за накладных расходов на управление потоками.
  • Синхронизация требуется при доступе к общим ресурсам, чтобы предотвратить взаимное исключение. Это напрямую приводит к увеличению использования памяти и ЦП.
  • Многопоточность увеличивает сложность программы, что также затрудняет отладку.
  • Это увеличивает вероятность потенциальных взаимоблокировок.
  • Это может привести к зависанию, когда поток не может регулярно обращаться к общему ресурсу. Приложение не сможет возобновить свою работу.

До сих пор вы читали о теоретических концепциях потоков. Если вы новичок в Python, мы рекомендуем прочитать наши 30 быстрых советов по кодированию Python, которые также могут помочь вам писать многопоточный код Python. Многие из наших читателей воспользовались этими советами и смогли улучшить свои навыки программирования.

Многопоточный модуль Python

Python предоставляет два модуля для реализации потоков в программах.

  • ****Модуль и
  • ****Модуль.

Примечание. К вашему сведению, в Python 2.x раньше было thread>модуль. Но это устарело в Python 3.xРавный акцентпо имени _thread>модули для обратной совместимости.

Основное различие между двумя модулями заключается в том, что модуль <_>нить> Реализовать потоки как функции. С другой стороны, threadingМодуль > обеспечивает объектно-ориентированный подход к созданию потоков.

Как создавать потоки с помощью модуля потоков?

Если вы решили подать заявку thread> module, затем используйте следующие методы для создания потоков.

#语法

thread.start_new_thread ( function, args[, kwargs] )

Этот подход очень эффективен и прост для создания потоков. Вы можете использовать его для запуска программ в Linux и Windows.

Этот метод запускает новый поток и возвращает его идентификатор. Он вызовет функцию, указанную в качестве параметра «функция», с переданным списком параметров. когда function> По возвращении поток завершится молча.

здесь,argsэто кортеж аргументов; вызовите function> не принимает аргументов. необязательный kwargsПараметр > указывает словарь аргументов ключевого слова.

**если function> Завершается с необработанным исключением, распечатывается трассировка стека и поток завершается (это не влияет на другие потоки, которые продолжают работать). Используйте приведенный ниже код, чтобы узнать больше о потоках.

Базовый пример многопоточности Python

#Python 多线程示例。
#1. 使用递归计算阶乘。
#2. 使用线程调用阶乘函数。

from _thread import start_new_thread
from time import sleep

threadId = 1 #线程计数器
waiting = 2 #2秒等待的时间

def factorial(n):
    global threadId
    rc = 0
    
    if n < 1:   # base case
        print("{}: {}".format('\nThread', threadId ))
        threadId += 1
        rc = 1
    else:
        returnNumber = n * factorial( n - 1 )  # recursive call
        print("{} != {}".format(str(n), str(returnNumber)))
        rc = returnNumber
    
    return rc

start_new_thread(factorial, (5, ))
start_new_thread(factorial, (4, ))

print("Waiting for threads to return...")
sleep(waiting)

Вы можете запустить приведенный выше код в своем локальном терминале Python или использовать любой онлайн-терминал Python. После выполнения этой программы она выдаст следующий вывод.

вывод программы

# Python 多线程:程序输出-
等待线程返回...

Thread: 1
1 != 1
2 != 2
3 != 6
4 != 24
5 != 120

Thread: 2
1 != 1
2 != 2
3 != 6
4 != 24

Как создавать потоки с помощью модуля потоков?

последнийthreading>модули более устаревшие, чем обсуждалось в предыдущем разделеthread> Модули предоставляют богатые возможности и улучшенную поддержку многопоточности. threading> Модули — хороший пример многопоточности в Python.

threading> модули объединяются thread> все методы модуля и предоставляет некоторые дополнительные методы

  • threading.activeCount():Он находит общее количество. Объект активного потока.
  • threading.currentThread():Вы можете использовать это, чтобы определить количество объектов потока в элементе управления потоком вызывающей стороны.
  • threading.enumerate():Это даст вам полный список активных в данный момент объектов потока.

В дополнение к вышеперечисленным методам threading>Модуль также обеспечиваетThread> можно попробовать реализовать многопоточность. Это объектно-ориентированный вариант многопоточности Python.

Thread> Класс публикует следующие методы.

метод класса Описание метода
run(): Это функция точки входа любого потока.
start(): Метод start() запускает поток при вызове метода run.
join([time]): Метод join() позволяет программе ожидать завершения потока.
isAlive(): Метод isAlive() проверяет активный поток.
getName(): Метод getName() извлекает имя потока.
setName(): Метод setName() обновляет имя потока.

Шаги для реализации потоков с использованием модуля Threading

Вы можете использовать threading> Модуль реализует новый поток.

  • от Thread> класс создает подкласс.
  • Переопределить init(self [,args])> способ предоставления параметров по мере необходимости.
  • Далее перепишите run(self [,args])> способ написать бизнес-логику потока.

Как только новый Thread>подкласс, он должен быть создан для запуска нового потока. Затем вызовите start()>метод его запуска. в конечном итоге он вызовет run()>способ выполнения бизнес-логики.

Пример. Создайте класс потока для печати даты

#Python 多线程示例打印当前日期。
#1. 使用 threading.Thread 类定义子类。
#2. 实例化子类并触发线程。

import threading
import datetime

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        print_date(self.name, self.counter)
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

# 创建新线程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 启动新线程
thread1.start()
thread2.start()

thread1.join()
thread2.join()
print("\nExiting the Program!!!")

вывод программы

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!

Многопоточность Python — синхронизация потоков

threading> Модули имеют встроенную функциональность для реализации блокировки, позволяющей синхронизировать потоки. Блокировка необходима для управления доступом к общим ресурсам, чтобы предотвратить повреждение или потерю данных.

вы можете позвонитьLock()метод для применения блокировки, который возвращает новый объект блокировки. Затем вы можете вызвать объект блокировкиполучить (заблокировать)метод, чтобы заставить поток работать синхронно.

по желаниюблокироватьПараметр указывает, ожидает ли поток получения блокировки.

  • Case Blocking= 0: поток немедленно вернет нулевое значение, если получение блокировки не удастся, и единицу, если блокировка будет успешной.
  • Case Blocking= 1: поток блокируется и ожидает снятия блокировки.

заблокировать объектrelease()Метод используется для снятия блокировки, когда она больше не нужна.

К вашему сведению, встроенные структуры данных Python (например, списки, словари) являются потокобезопасными, потому что они имеют побочный эффект атомарных байт-кодов, используемых для управления ими. Другие структуры данных или примитивные типы, реализованные в Python, такие как целые числа и числа с плавающей запятой, не имеют этой защиты. Чтобы предотвратить одновременный доступ к объекту, мы используемLockобъект.

Пример заблокированной многопоточности

#Python 多线程示例来演示锁定。
#1. 使用 threading.Thread 类定义子类。
#2. 实例化子类并触发线程。
#3. 在线程的 run 方法中实现锁。

import threading
import datetime

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        # 获取锁同步线程
        threadLock.acquire()
        print_date(self.name, self.counter)
        # 为下一个线程释放锁
        threadLock.release()
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 启动新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有线程完成
for thread in threads:
    thread.join()

print("\nExiting the Program!!!")

вывод программы

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!

Резюме - Многопоточность Python для начинающих

Я надеюсь, что вы найдете это руководство по многопоточности Python интересным и увлекательным. Если вам понравилась эта статья и вы хотите увидеть больше, вы можете прочитать ее здесь (Github/Gitee) Следуйте за мной, чтобы увидеть больше информации, вот сводка всего моего оригинального и исходного кода

🧵 Другие статьи по теме

Рекомендуемые статьи из прошлого:

Если вы действительно узнали что-то новое из этой статьи, ставьте лайк, добавляйте в закладки и делитесь с друзьями. 🤗Наконец, не забудьте поддержать ❤ или 📑