Лаб. 5 Python (Вариант 1, 1, 1)
.docx
import threading import time semaphore = threading.Semaphore(5) def semaphoreTest(): with semaphore: print(f"Вызвался {threading.current_thread().name}") time.sleep(5) for i in range(12): threading.Thread(target=semaphoreTest, name=f"поток №{i}").start() ''' # Инициализация семафора с начальным значением 1 semaphore = threading.Semaphore(1) def thread_1(): print("Поток 1 перед блокировкой") semaphore.acquire() # Захват семафора print("Поток 1 блокировка") #time.sleep(5) def thread_2(): print("Поток 2 перед блокировкой") semaphore.acquire() # Захват семафора print("Поток 2 блокировка") #time.sleep(5) def thread_3(): print("Поток 3 перед освобождением") semaphore.release() # Освобождение семафора print("Поток 3 после освобождение") #time.sleep(5) # Создание и запуск потоков t1 = threading.Thread(target=thread_1) t2 = threading.Thread(target=thread_2) t3 = threading.Thread(target=thread_3) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print("FINISH") '''
import time from concurrent import futures from random import randint N = 80 Q = [] P = [] for i in range(N): Q.append(randint(-10,10)) P.append(randint(-10,10)) def calculate_element(i, j): return 1 / 1 + abs(Q[j] - P[i]) startTime = time.time() R1 = [] for i in range(N): row1 = [] for j in range(N): element = calculate_element(i, j) row1.append(element) R1.append(row1) endTime = time.time() measuredTime = endTime - startTime print("Время выполнения без использования concurrent.futures:", measuredTime) startTime = time.time() with futures.ThreadPoolExecutor(max_workers=5) as executor: R2 = [] #futures_list = [] for i in range(N): row2 = [] for j in range(N): a = executor.submit(calculate_element,i, j) row2.append(a.result()) #row2.append(executor.submit(calculate_element, i, j)) R2.append(row2) endTime = time.time() measuredTime = endTime - startTime print("Время выполнения с использованием concurrent.futures:", measuredTime) ''' start_time = time.time() futures_list = [] with futures.ThreadPoolExecutor(max_workers=5) as executor: indices = [(i, j) for i in range(N) for j in range(N)] results = executor.map(calculate_element, indices) # Преобразование результатов в матрицу R for i in range(N*N): #row3 = list(results) futures_list.append(results) end_time = time.time() execution_time = end_time - start_time print("Время выполнения с использованием concurrent.futures:", execution_time) R3 = [] for i in range(N): R3.append([]) count= 0 for q in range(N): for i in range(count, count + N): R3[q].append(futures_list[i]) count+=N ''' #print(R1) #print(R2) #print(R3)
import requests import time import concurrent.futures sites = [ 'https://www.google.ru', 'https://www.python.org', 'https://orioks.miet.ru', 'https://www.ozon.ru', 'https://www.microsoft.com', 'https://www.amazon.com', 'https://www.wildberries.ru', 'https://shop.hajimerecords.com', 'https://www.eldorado.ru', 'https://web.telegram.org' ] def get_and_save_sites(site): response = requests.get(site) #делает запрос к сайту content = response.text #получение информации filename = site.split('//')[1].split('.')[1] + '.txt' with open(filename, 'w') as file: file.write(content) startTime = time.time() for site in sites: get_and_save_sites(site) endTime = time.time() measuredTime = endTime - startTime print("Время выполнения в одном потоке:", measuredTime) startTime = time.time() with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: [executor.submit(get_and_save_sites, site) for site in sites] endTime = time.time() measuredTime = endTime - startTime print("Время выполнения в нескольких потоках:", measuredTime)
Поток – подзадача, выполняемая внутри процесса. Процесс имеет собственную память, потоки разделяют память процесса.
Процесс – экземпляр выполняемой программы.
Многопроцессорность – одновременное выполнение нескольких процессов. Многопроцессорность выполнение нескольких независимых процессов, а многопоточность выполнение нескольких потоков внутри одного процесса.
Thread(target, args) - создает новый поток выполнения.
Thread.getName() - возвращает имя потока.
Thread.setName(name) - устанавливает имя потока.
Thread.start() - запускает выполнение потока.
Thread.join(timeout) - ожидает завершения потока.
Thread.is_alive() - возвращает True, если поток выполняется.
Process(target, args) - создает новый процесс выполнения.
Process.start() - запускает выполнение процесса.
Process.join(timeout) - ожидает завершения процесса.
Process.is_alive() - возвращает True, если процесс выполняется.
Процесс-демон – процесс, выполняемый в фоновом режиме, и не является основным процессом. Завершается вместе с основным процессомю
GIL (Global Interpreter Lock) - механизм, который ограничивает одновременное выполнение нескольких потоков внутри одного процесса.
GIL предотвращает одновременное выполнение кода в нескольких потоках. Даже если есть множество потоков, только один поток может выполняться одновременно, в то время как остальные потоки ожидают освобождения GIL. Это происходит из-за того, что GIL был введен для обеспечения безопасности работы с объектами в памяти Python и избежания состояний гонки.
Модуль threading значительно упрощает работу с потоками и позволяет программировать запуск нескольких операций одновременно. Потоки в Python лучше всего работают с операциями I/O, такими как загрузка ресурсов из интернета или чтение файлов и папок на вашем компьютере. Это связано с тем, что I/O операции, запущенные интерпретатором Python, выполняются операционной системой. В это время интерпретатор Python может продолжать исполнять код в другом потоке, пока I/O операция, выполняемая операционной системой, не завершится.
Модуль multiprocessing в Python предназначен для выполнения CPU-интенсивных задач, которые могут быть разделены на независимые подзадачи. Он хорошо подходит для параллельной обработки данных, выполнения вычислений, распределения задач на несколько ядер процессора и т.д. Каждый процесс в multiprocessing имеет свою собственную память и ресурсы, поэтому он может использоваться для максимальной загрузки процессора и параллельной обработки.
Если программа является однопоточной или не требует параллельного выполнения.
Если в программе есть критические секции или общие ресурсы, которые могут привести к состояниям гонки. В таких случаях может потребоваться использовать механизмы синхронизации, такие как блокировки или очереди.
Если программа выполняет операции, которые блокируют GIL и приводят к замедлению всего приложения. В таких случаях может потребоваться использовать многопроцессорность, чтобы избежать ограничений GIL.
Основная идея синхронизации потоков при помощи блокировки заключается в том, чтобы обеспечить согласованность и безопасность доступа к общим ресурсам во время параллельного выполнения потоков. Блокировки позволяют потокам получать эксклюзивный доступ к критическим секциям кода или общим данным, блокируя доступ других потоков до тех пор, пока текущий поток не завершит свою работу или не освободит блокировку.
Импортирование модуля threading. Создание экземпляра блокировки с помощью threading.Lock(). Установка блокировки с помощью метода lock.acquire(). По завершении работы с критической секцией кода или общими данными освобождение блокировки с помощью lock.release().
Основная идея структуры данных очереди заключается в упорядоченном хранении элементов и обеспечении операций добавления нового элемента в конец очереди и удаления элемента из начала очереди.
Очереди предоставляют механизмы для безопасного обмена данными между потоками или процессами, гарантируя, что только один поток или процесс может получить доступ к элементу очереди в определенный момент времени. Это позволяет синхронизировать доступ к общим ресурсам и предотвратить состояние гонки.
В очередях с приоритетами элементы имеют приоритеты, которые определяют порядок их извлечения. Каждый элемент имеет свой приоритет, и при извлечении элемента выбирается элемент с наивысшим приоритетом. Элементы с более высоким приоритетом извлекаются раньше элементов с более низким приоритетом.