Ответ
Разделяемая память (shared memory) — это механизм межпроцессного взаимодействия (IPC), при котором несколько независимых процессов получают доступ к одному и тому же участку физической памяти. Это один из самых быстрых способов обмена данными, так как исключает затраты на копирование данных между процессами.
В Python, начиная с версии 3.8, для работы с разделяемой памятью используется модуль multiprocessing.shared_memory
.
Ключевые шаги:
- Создание: Один процесс создает блок разделяемой памяти с помощью
shared_memory.SharedMemory(create=True, size=...)
. - Подключение: Другие процессы подключаются к этому блоку по его уникальному имени
shared_memory.SharedMemory(name=...)
. - Работа с данными: Данные записываются и читаются через буфер (
.buf
), который представляет собойmemoryview
. - Освобождение ресурсов: Каждый процесс должен закрыть свой экземпляр (
.close()
), а создавший процесс — дополнительно удалить блок из системы (.unlink()
).
Пример: один процесс пишет, другой читает
import multiprocessing as mp
from multiprocessing import shared_memory
import time
def writer(shm_name):
# Подключаемся к существующей памяти
existing_shm = shared_memory.SharedMemory(name=shm_name)
print("Writer: подключился к памяти.")
# Записываем данные в первые 5 байт
message = b'Hello'
existing_shm.buf[:len(message)] = message
print("Writer: записал данные.")
# Закрываем доступ
existing_shm.close()
def reader(shm_name):
time.sleep(1) # Ждем, пока writer запишет данные
# Подключаемся к существующей памяти
existing_shm = shared_memory.SharedMemory(name=shm_name)
print("Reader: подключился к памяти.")
# Читаем первые 5 байт
read_message = bytes(existing_shm.buf[:5])
print(f"Reader: прочитал данные - {read_message.decode()}")
existing_shm.close()
if __name__ == "__main__":
# 1. Создаем блок разделяемой памяти
shm = shared_memory.SharedMemory(create=True, size=10)
print(f"Main: создал блок памяти с именем '{shm.name}'")
# 2. Запускаем процессы
p_writer = mp.Process(target=writer, args=(shm.name,))
p_reader = mp.Process(target=reader, args=(shm.name,))
p_writer.start()
p_reader.start()
p_writer.join()
p_reader.join()
# 3. Освобождаем и удаляем ресурсы
shm.close()
shm.unlink()
print("Main: память освобождена.")
Важные аспекты:
- Синхронизация: Разделяемая память не обеспечивает синхронизацию. Для предотвращения гонки данных (race conditions) необходимо использовать примитивы синхронизации, такие как
multiprocessing.Lock
илиSemaphore
. - Управление жизненным циклом: Крайне важно корректно вызывать
close()
иunlink()
, чтобы избежать утечек ресурсов в операционной системе.