Ответ
Мьютекс и семафор — это примитивы синхронизации, используемые для управления доступом к общим ресурсам в многопоточной среде. Их ключевое различие заключается в назначении и механизме работы.
Мьютекс (Mutex - Mutual Exclusion)
Назначение: Обеспечить взаимное исключение. Мьютекс гарантирует, что только один поток может получить доступ к критической секции кода или ресурсу в любой момент времени.
Принцип работы: Работает как двоичный замок (заблокирован/разблокирован). Если ресурс свободен, поток захватывает мьютекс и блокирует его. Другие потоки, пытающиеся захватить тот же мьютекс, будут заблокированы до тех пор, пока владелец его не освободит.
Ключевая особенность: Концепция "владения". Только тот поток, который захватил мьютекс, может его освободить.
from threading import Lock, Thread
# В Python мьютекс представлен классом Lock
lock = Lock()
shared_resource = 0
def task():
global shared_resource
for _ in range(100000):
lock.acquire() # Захват мьютекса
try:
shared_resource += 1 # Критическая секция
finally:
lock.release() # Освобождение мьютекса
# Запуск потоков...
Семафор (Semaphore)
Назначение: Ограничить доступ к ресурсу определенным количеством потоков.
Принцип работы: Работает как счетчик. При инициализации семафору задается начальное значение (например, 5), которое означает, что 5 потоков могут одновременно получить доступ к ресурсу. Каждый раз, когда поток захватывает семафор, счетчик уменьшается. Когда он освобождает — увеличивается. Если счетчик равен нулю, новые потоки блокируются.
Типы:
- Счетный семафор (counting semaphore): счетчик > 1.
- Двоичный семафор (binary semaphore): счетчик равен 1, по поведению очень похож на мьютекс.
from threading import Semaphore, Thread
import time
# Ограничиваем доступ к ресурсу тремя потоками одновременно
semaphore = Semaphore(3)
def access_resource(thread_id):
print(f"Поток {thread_id} пытается получить доступ...")
with semaphore: # Автоматический acquire/release
print(f"Поток {thread_id} получил доступ!")
time.sleep(2)
print(f"Поток {thread_id} освобождает ресурс.")
# Запуск 5 потоков, но одновременно работать будут только 3
threads = [Thread(target=access_resource, args=(i,)) for i in range(5)]
for t in threads: t.start()
Сравнительная таблица
Критерий | Мьютекс (Mutex) | Семафор (Semaphore) |
---|---|---|
Назначение | Взаимное исключение (защита ресурса) | Ограничение доступа (контроль параллелизма) |
Кол-во потоков | Только один | N (заданное число) |
Владение | Принадлежит потоку, который его захватил | Не имеет концепции владения |
Аналогия | Ключ от одной туалетной комнаты | Набор из N ключей от одинаковых душевых кабинок |