Каква е разликата между семафор и мютекс?
sobes.tech AI
Отговор от AI
Семафорът е обобщен механизъм за синхронизация, използван за управление на достъпа до ограничен ресурс от няколко конкуриращи се потока. Той поддържа цяло число, което намалява при захващане на ресурса и се увеличава при освобождаване. Ако стойността на семафора е нула, опитът за захващане блокира потока, докато друг поток не освободи ресурса. Може да се използва за ограничаване на броя на едновременно работещите потоци.
Мютекс (mutual exclusion — взаимно изключване) е бинарен семафор, който може да бъде в блокирано или в разблокирано състояние. Той се използва за защита на критична секция от едновременен достъп от няколко потока. Само един поток може да захване мютекса в даден момент. Потокът, който е захванал мютекса, не може да бъде прекъснат от друг поток, който се опитва да захване същия мютекс. Ако се опитате да захванете блокирания мютекс, потокът ще бъде блокиран до неговото освобождаване.
Ключови разлики:
| Характеристика | Семафор | Мютекс |
|---|---|---|
| Тип | Обобщен механизъм за синхронизация | Бинарен семафор (специален случай на семафор) |
| Стойност | Цяло число (>= 0) | Бинарен (0 или 1) |
| Назначение | Управление на достъпа до ресурси, ограничение | Защита на критични секции, взаимно изключване |
| Владелец | Може да няма собственик | Винаги има собственик (потокът, който го е захванал) |
| Използване в iOS | DispatchSemaphore |
Често се реализира чрез DispatchQueue.sync или NSRecursiveLock в някои сценарии |
Пример за използване на мютекс за защита на критична секция:
// В контекста на GCD (Grand Central Dispatch)
let serialQueue = DispatchQueue(label: "com.example.criticalSection")
serialQueue.sync {
// Критична секция код
// Само един поток може да бъде тук във всеки момент
}
Пример за използване на семафор за ограничаване на паралелните задачи:
// В контекста на GCD (Grand Central Dispatch)
let semaphore = DispatchSemaphore(value: 3) // Позволява 3 паралелни задачи
DispatchQueue.global().async {
semaphore.wait() // Намалява стойността на семафора с 1. Блокира, ако стойността е 0.
// Код на задачата, изпълнявана паралелно
print("Задачата се изпълнява")
Thread.sleep(forTimeInterval: 1) // Имитиране на работа
semaphore.signal() // Увеличава стойността на семафора с 1. Освобождава чакащия поток, ако има такъв.
print("Задачата е завършена")
}
// Може да стартирате няколко такива блока. Само 3 ще се изпълняват едновременно.