Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Егор Толстой
Ведущий iOS разработчик @ Rambler&Co
Задачи синхронизации
Классические и прикладные решения
Синхронизация
• Что такое синхронизация
• Решение проблем синхронизации
• Классические задачи
синхронизации
Синхронизация
• Синхронизация - 

обеспечение правильной
совместной работы нескольких
потоков.
Синхронизация
Алиса
Боб
Поток 1 Поток 2
Синхронизация
Алиса Боб
Поток 1 Поток 2
Синхронизация
Алиса Боб
Поток 1 Поток 2
Синхронизация
Алиса
Боб
Поток 1 Поток 2
Синхронизация
• Состояние гонки - 

работа приложения зависит от
последовательности вызова
секции его кода разными
потокам...
Синхронизация
func incrementSharedVariable {
// counter == 0
counter += 1
}
Синхронизация
func incrementSharedVariable {
// counter == 0
counter += 1
}
Поток 1 Поток 2 Поток 3
Синхронизация
func incrementSharedVariable {
// counter == 0
counter += 1
}
Поток 1 Поток 2 Поток 3
counter ∈ [1,3]
Синхронизация
• Критическая секция - 

участок кода, в котором
одновременно может находиться
только один поток.
Синхронизация
func incrementSharedVariable {
lockSection()
counter += 1
unlockSection()
}
Синхронизация
Поток 1 Поток 2 Поток 3
func incrementSharedVariable {
lockSection()
counter += 1
unlockSection()
}
Синхронизация
Поток 1 Поток 2 Поток 3
func incrementSharedVariable {
lockSection()
counter += 1
unlockSection()
}
Синхронизация
Поток 1 Поток 2 Поток 3
func incrementSharedVariable {
lockSection()
counter += 1
unlockSection()
}
Синхронизация
Поток 1 Поток 2 Поток 3
func incrementSharedVariable {
lockSection()
counter += 1
unlockSection()
}
counter ...
Синхронизация
• Deadlock - 

несколько потоков блокируют
выполнение друг друга.
Синхронизация
• У каждой задачи синхронизации
есть определенные условия.
Синхронизация
Алиса Боб
Поток 1 Поток 2
Синхронизация
Алиса
Боб
Поток 1 Поток 2
Синхронизация
Алиса
Боб
Поток 1 Поток 2
Синхронизация
Алиса Боб
Поток 1 Поток 2
Синхронизация
• Передача сообщений между
потоками - простое решение
большинства проблем.
Синхронизация
Алиса Боб
а1: Съесть завтрак
а2: Поработать
а3: Съесть обед
а4: Позвонить Бобу
б1: Съесть завтрак
б2: Дождат...
Синхронизация
Алиса Боб
а1: Съесть завтрак
а2: Поработать
а3: Съесть обед
а4: Позвонить Бобу
б1: Съесть завтрак
б2: Дождат...
Синхронизация
Алиса Боб
а1: Съесть завтрак
а2: Поработать
а3: Съесть обед
а4: Позвонить Бобу
б1: Съесть завтрак
б2: Дождат...
Синхронизация
• События считаются
параллельными, если, изучив код
программы, мы не можем
утверждать, какое из них
произойд...
Синхронизация
0
Алиса
Семафор
Боб
Синхронизация
0
Алиса
Семафор
Боб
Синхронизация
wait0
Алиса
Семафор
Боб
Синхронизация
wait-1
Алиса
Семафор
Боб
Синхронизация
wait-1Алиса
Семафор
Боб
Синхронизация
signal wait-1Алиса
Семафор
Боб
Синхронизация
signal wait0Алиса
Семафор
Боб
Синхронизация
signal wait0
Алиса
Семафор
Боб
Синхронизация
• Семафор создается с начальным
значением,
• wait - уменьшает счетчик,
• signal - увеличивает счетчик.
Синхронизация
• Задача "Читатели-Писатели" 

Readers-Writers problem
Синхронизация
• Любое количество читателей в
критической секции
• Единственный писатель в
критической секции
Синхронизация
1.
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
Синхронизация
1.
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
Синхронизация
1.
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
Синхронизация
1.
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
Синхронизация
1.
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
Синхронизация
0.
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
1
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
2
0.
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
2
-1.
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
2
-1.
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
2
-1.
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
2
-1.
Синхронизация
Семафор
"комната пуста"
on
Выключатель
"читатели"
Читатели Писатели
1
-1.
Синхронизация
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
0.
Синхронизация
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
0.
Синхронизация
Семафор
"комната пуста"
off
Выключатель
"читатели"
Читатели Писатели
0
1.
Синхронизация
• Голод - состояние, в котором
поток может бесконечно ждать
своей очереди. 

А может и дождаться.
Синхронизация
• Решение с использованием
NSOperation
Синхронизация
class OperationScheduler {
var readerQueue = NSOperationQueue()
var writerQueue = NSOperationQueue()
init ()...
Синхронизация
func addReaderOperation(operation: NSBlockOperation) {
// Зависим от выполнения всех писателей
for writerOpe...
Синхронизация
func addWriterOperation(operation: NSBlockOperation) {
// Все читатели зависят от нового писателя
for reader...
Синхронизация
func readersWriters() {
let scheduler = OperationScheduler()
scheduler.addWriter()
for i in 1...5 {
schedule...
Синхронизация
• Задача "Обедающие философы" 

Dining philosophers problem
Синхронизация
while(true) {
think()
getForks()
eat()
putForks()
}
Синхронизация
• Не больше одного философа на
вилку
• Не допустить deadlock
• Не допустить голод
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
вилка
1
вилка
1
вилка 1 вилка
1
вилка1
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
deadlock :(
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
Семафор
"официант"
4
вилка
1
вилка
1
вилка 1 вилка
1
вилка1
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
Семафор
"официант"
3
вилка
1
вилка
1
вилка 1 вилка
1
вилка1
Синхронизация
Ф.5
Ф.1
Ф.2
Ф.3
Ф.4
Семафор
"официант"
3
вилка
0
вилка
1
вилка 0 вилка
1
вилка1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
вилка 0 вилка
1
вилка1
Ф.2
Семафор
"официант"
2
Ф.1
1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
1
вилка1
Ф.2
Семафор
"официант"
2
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
1
вилка1
Ф.2
Семафор
"официант"
1
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка1
Ф.2
Семафор
"официант"
1
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка1
Ф.2
Семафор
"официант"
0
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Ф.2
Семафор
"официант"
0
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 1 вилка
0
вилка0
Ф.2
Семафор
"официант"
1
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Ф.2
Семафор
"официант"
0
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
1
вилка
0
вилка 0 вилка
0
вилка0
Ф.2
Семафор
"официант"
1
Ф.1
Синхронизация
Ф.5
Ф.3
Ф.4
вилка
0
вилка
0
вилка 0 вилка
0
вилка0
Ф.2
Семафор
"официант"
0
Ф.1
Синхронизация
• Решение с использованием
NSOperation
Синхронизация
class DiningPhilosophersOperationScheduler {
var philosopherQueues = [NSOperationQueue]()
init() {
for _ in ...
Синхронизация
class PhilosopherBlockOperation: NSBlockOperation {
init(index: Int) {
super.init()
addExecutionBlock({
prin...
Синхронизация
func startPhilosopher(index: Int) {
let operation = PhilosopherBlockOperation(index: index)
let leftQueue = ...
Синхронизация
func diningPhilosophers() {
let scheduler =
DiningPhilosophersOperationScheduler()
scheduler.startPhilosophe...
Синхронизация
> philosopher 0 is thinking
> philosopher 0 is eating
> philosopher 3 is thinking
> philosopher 3 is eating
...
Синхронизация
• Задача "Собираем H2O" 

Building H2O problem
Синхронизация
• Кислород ждет двух потоков
водорода
• Водород ждет одного потока
водорода и одного - кислорода
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О
H
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О H
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
-1
3
Барьер
О H
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
-1
3
Барьер
О H
H
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
-1
3
Барьер
О H H
Синхронизация
-1
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
-2
3
Барьер
О H H
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О H H
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
О H H
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
0
Барьер
О H H
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
0
Барьер
О H H
Синхронизация
0
Семафор
"Кислород"
Кислород Водород
Семафор
"Водород"
0
3
Барьер
Синхронизация
• Решение с использованием
NSOperation
Синхронизация
func triggerHydrogenEvent(location: CGPoint) {
let sprite = AtomNode.atom(AtomSprite.Hydrogen, location: loc...
Синхронизация
class H2OOperationScheduler {
let moleculeQueue = NSOperationQueue()
// Этот блок вызывается при успешном сб...
Синхронизация
func addHydrogen(node: SKSpriteNode, block: () -> Void) {
let currentMolecule = obtainMolecule { (molecule) ...
Синхронизация
class H2OOperation: NSOperation {
let atomQueue = NSOperationQueue()
let moleculeBlock: (Array<SKSpriteNode>...
Синхронизация
class H2OOperation: NSOperation {
...
override func main() {
atomQueue.suspended = false
atomQueue.waitUntil...
Синхронизация
• Синхронизация - это непросто
• Синхронизация - это интересно
• Синхронизация - это важно
Синхронизация
• Код примеров:

https://github.com/rambler-
digital-solutions/synchronization-
problems
Синхронизация
• The Little Book of Semaphores

Allen B. Downey



http://www.greenteapress.com/
semaphores/
Upcoming SlideShare
Loading in …5
×

Rambler.iOS #4: Задачи синхронизации. Классические и прикладные решения.

1,355 views

Published on

Rambler.iOS #4: Задачи синхронизации. Классические и прикладные решения. (Толстой Егор).

Rambler.iOS - митапы iOS-разработчиков, организуемые компанией RAMBLER&Co.

Published in: Technology
  • Be the first to comment

Rambler.iOS #4: Задачи синхронизации. Классические и прикладные решения.

  1. 1. Егор Толстой Ведущий iOS разработчик @ Rambler&Co Задачи синхронизации Классические и прикладные решения
  2. 2. Синхронизация • Что такое синхронизация • Решение проблем синхронизации • Классические задачи синхронизации
  3. 3. Синхронизация • Синхронизация - 
 обеспечение правильной совместной работы нескольких потоков.
  4. 4. Синхронизация Алиса Боб Поток 1 Поток 2
  5. 5. Синхронизация Алиса Боб Поток 1 Поток 2
  6. 6. Синхронизация Алиса Боб Поток 1 Поток 2
  7. 7. Синхронизация Алиса Боб Поток 1 Поток 2
  8. 8. Синхронизация • Состояние гонки - 
 работа приложения зависит от последовательности вызова секции его кода разными потоками.
  9. 9. Синхронизация func incrementSharedVariable { // counter == 0 counter += 1 }
  10. 10. Синхронизация func incrementSharedVariable { // counter == 0 counter += 1 } Поток 1 Поток 2 Поток 3
  11. 11. Синхронизация func incrementSharedVariable { // counter == 0 counter += 1 } Поток 1 Поток 2 Поток 3 counter ∈ [1,3]
  12. 12. Синхронизация • Критическая секция - 
 участок кода, в котором одновременно может находиться только один поток.
  13. 13. Синхронизация func incrementSharedVariable { lockSection() counter += 1 unlockSection() }
  14. 14. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable { lockSection() counter += 1 unlockSection() }
  15. 15. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable { lockSection() counter += 1 unlockSection() }
  16. 16. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable { lockSection() counter += 1 unlockSection() }
  17. 17. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable { lockSection() counter += 1 unlockSection() } counter == 3
  18. 18. Синхронизация • Deadlock - 
 несколько потоков блокируют выполнение друг друга.
  19. 19. Синхронизация • У каждой задачи синхронизации есть определенные условия.
  20. 20. Синхронизация Алиса Боб Поток 1 Поток 2
  21. 21. Синхронизация Алиса Боб Поток 1 Поток 2
  22. 22. Синхронизация Алиса Боб Поток 1 Поток 2
  23. 23. Синхронизация Алиса Боб Поток 1 Поток 2
  24. 24. Синхронизация • Передача сообщений между потоками - простое решение большинства проблем.
  25. 25. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3
  26. 26. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3
  27. 27. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3 б3 > б2 > a4 > a3
  28. 28. Синхронизация • События считаются параллельными, если, изучив код программы, мы не можем утверждать, какое из них произойдет первым.
  29. 29. Синхронизация 0 Алиса Семафор Боб
  30. 30. Синхронизация 0 Алиса Семафор Боб
  31. 31. Синхронизация wait0 Алиса Семафор Боб
  32. 32. Синхронизация wait-1 Алиса Семафор Боб
  33. 33. Синхронизация wait-1Алиса Семафор Боб
  34. 34. Синхронизация signal wait-1Алиса Семафор Боб
  35. 35. Синхронизация signal wait0Алиса Семафор Боб
  36. 36. Синхронизация signal wait0 Алиса Семафор Боб
  37. 37. Синхронизация • Семафор создается с начальным значением, • wait - уменьшает счетчик, • signal - увеличивает счетчик.
  38. 38. Синхронизация • Задача "Читатели-Писатели" 
 Readers-Writers problem
  39. 39. Синхронизация • Любое количество читателей в критической секции • Единственный писатель в критической секции
  40. 40. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0
  41. 41. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0
  42. 42. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0
  43. 43. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0
  44. 44. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0
  45. 45. Синхронизация 0. Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 1
  46. 46. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2 0.
  47. 47. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2 -1.
  48. 48. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2 -1.
  49. 49. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2 -1.
  50. 50. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2 -1.
  51. 51. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 1 -1.
  52. 52. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0 0.
  53. 53. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0 0.
  54. 54. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0 1.
  55. 55. Синхронизация • Голод - состояние, в котором поток может бесконечно ждать своей очереди. 
 А может и дождаться.
  56. 56. Синхронизация • Решение с использованием NSOperation
  57. 57. Синхронизация class OperationScheduler { var readerQueue = NSOperationQueue() var writerQueue = NSOperationQueue() init () { // Читатели должны выполняться параллельно readerQueue.maxConcurrentOperationCount = MAX // Писатели должны выполняться последовательно writerQueue.maxConcurrentOperationCount = 1 } ... }
  58. 58. Синхронизация func addReaderOperation(operation: NSBlockOperation) { // Зависим от выполнения всех писателей for writerOperation in writerQueue.operations { operation.addDependency(writerOperation) } readerQueue.addOperation(operation) }
  59. 59. Синхронизация func addWriterOperation(operation: NSBlockOperation) { // Все читатели зависят от нового писателя for readerOperation in readerQueue.operations { readerOperation.addDependency(operation) } writerQueue.addOperation(operation) }
  60. 60. Синхронизация func readersWriters() { let scheduler = OperationScheduler() scheduler.addWriter() for i in 1...5 { scheduler.addReader(i) } scheduler.addWriter() } > writer fired > writer fired > reader 2 fired > reader 3 fired > reader 1 fired > reader 5 fired > reader 4 fired
  61. 61. Синхронизация • Задача "Обедающие философы" 
 Dining philosophers problem
  62. 62. Синхронизация while(true) { think() getForks() eat() putForks() }
  63. 63. Синхронизация • Не больше одного философа на вилку • Не допустить deadlock • Не допустить голод
  64. 64. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 1 вилка 1 вилка 1 вилка 1 вилка1
  65. 65. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0
  66. 66. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0
  67. 67. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0
  68. 68. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0 deadlock :(
  69. 69. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 4 вилка 1 вилка 1 вилка 1 вилка 1 вилка1
  70. 70. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 3 вилка 1 вилка 1 вилка 1 вилка 1 вилка1
  71. 71. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 3 вилка 0 вилка 1 вилка 0 вилка 1 вилка1
  72. 72. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка вилка 0 вилка 1 вилка1 Ф.2 Семафор "официант" 2 Ф.1 1
  73. 73. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 1 вилка1 Ф.2 Семафор "официант" 2 Ф.1
  74. 74. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 1 вилка1 Ф.2 Семафор "официант" 1 Ф.1
  75. 75. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка1 Ф.2 Семафор "официант" 1 Ф.1
  76. 76. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка1 Ф.2 Семафор "официант" 0 Ф.1
  77. 77. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0 Ф.2 Семафор "официант" 0 Ф.1
  78. 78. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 1 вилка 0 вилка0 Ф.2 Семафор "официант" 1 Ф.1
  79. 79. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0 Ф.2 Семафор "официант" 0 Ф.1
  80. 80. Синхронизация Ф.5 Ф.3 Ф.4 вилка 1 вилка 0 вилка 0 вилка 0 вилка0 Ф.2 Семафор "официант" 1 Ф.1
  81. 81. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0 вилка 0 вилка0 Ф.2 Семафор "официант" 0 Ф.1
  82. 82. Синхронизация • Решение с использованием NSOperation
  83. 83. Синхронизация class DiningPhilosophersOperationScheduler { var philosopherQueues = [NSOperationQueue]() init() { for _ in 0...4 { let philosopherQueue = NSOperationQueue() philosopherQueue.maxConcurrentOperationCount = 1 philosopherQueues.append(philosopherQueue) } } ... }
  84. 84. Синхронизация class PhilosopherBlockOperation: NSBlockOperation { init(index: Int) { super.init() addExecutionBlock({ print("philosopher (index) is eating") sleep(2) print("philosopher (index) puts forks") }) } }
  85. 85. Синхронизация func startPhilosopher(index: Int) { let operation = PhilosopherBlockOperation(index: index) let leftQueue = getLeftPhilosopher(index) let leftPhilosopherEats = leftQueue.operationCount > 0 if (leftPhilosopherEats) { for leftOperation in leftQueue.operations { operation.addDependency(leftOperation) } } // То же и для правого соседа let currentPhilosopherQueue = philosopherQueues[index] currentPhilosopherQueue.addOperation(operation) }
  86. 86. Синхронизация func diningPhilosophers() { let scheduler = DiningPhilosophersOperationScheduler() scheduler.startPhilosopher(0) scheduler.startPhilosopher(3) scheduler.startPhilosopher(2) scheduler.startPhilosopher(1) scheduler.startPhilosopher(4) } > philosopher 0 is thinking > philosopher 0 is eating > philosopher 3 is thinking > philosopher 3 is eating > philosopher 2 is thinking > philosopher 1 is thinking > philosopher 4 is thinking > philosopher 3 puts forks > philosopher 0 puts forks > philosopher 2 is eating > philosopher 4 is eating > philosopher 2 puts forks > philosopher 4 puts forks > philosopher 1 is eating > philosopher 1 puts forks
  87. 87. Синхронизация > philosopher 0 is thinking > philosopher 0 is eating > philosopher 3 is thinking > philosopher 3 is eating > philosopher 2 is thinking > philosopher 1 is thinking > philosopher 4 is thinking > philosopher 3 puts forks > philosopher 0 puts forks > philosopher 2 is eating > philosopher 4 is eating > philosopher 2 puts forks > philosopher 4 puts forks > philosopher 1 is eating > philosopher 1 puts forks Ф.0 Ф.1 Ф.2 Ф.3 Ф.4
  88. 88. Синхронизация • Задача "Собираем H2O" 
 Building H2O problem
  89. 89. Синхронизация • Кислород ждет двух потоков водорода • Водород ждет одного потока водорода и одного - кислорода
  90. 90. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер
  91. 91. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О
  92. 92. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О
  93. 93. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О H
  94. 94. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О H
  95. 95. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3 Барьер О H
  96. 96. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3 Барьер О H H
  97. 97. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3 Барьер О H H
  98. 98. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -2 3 Барьер О H H
  99. 99. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О H H
  100. 100. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер О H H
  101. 101. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 0 Барьер О H H
  102. 102. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 0 Барьер О H H
  103. 103. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3 Барьер
  104. 104. Синхронизация • Решение с использованием NSOperation
  105. 105. Синхронизация func triggerHydrogenEvent(location: CGPoint) { let sprite = AtomNode.atom(AtomSprite.Hydrogen, location: location) self.addChild(sprite) self.scheduler.addHydrogen(sprite, block: atomBlock(sprite)) }
  106. 106. Синхронизация class H2OOperationScheduler { let moleculeQueue = NSOperationQueue() // Этот блок вызывается при успешном сборе молекулы H2O var moleculeBlock: (Array<SKSpriteNode>) -> Void init(H2OBlock: (Array<SKSpriteNode>) -> Void) { moleculeQueue.maxConcurrentOperationCount = 1 moleculeBlock = H2OBlock } ... }
  107. 107. Синхронизация func addHydrogen(node: SKSpriteNode, block: () -> Void) { let currentMolecule = obtainMolecule { (molecule) -> Bool in return molecule.hydrogen < 2 } let operation = AtomOperation(node: node, block: block) currentMolecule.addHydrogen(operation) }
  108. 108. Синхронизация class H2OOperation: NSOperation { let atomQueue = NSOperationQueue() let moleculeBlock: (Array<SKSpriteNode>) -> Void var nodes = Array<SKSpriteNode>() ... override var ready: Bool { return hydrogen == 2 && oxygen == 1 } func addHydrogen(operation: AtomOperation) { nodes.append(operation.node) atomQueue.addOperation(operation) hydrogen++ } }
  109. 109. Синхронизация class H2OOperation: NSOperation { ... override func main() { atomQueue.suspended = false atomQueue.waitUntilAllOperationsAreFinished() self.moleculeBlock(nodes) } ... }
  110. 110. Синхронизация • Синхронизация - это непросто • Синхронизация - это интересно • Синхронизация - это важно
  111. 111. Синхронизация • Код примеров:
 https://github.com/rambler- digital-solutions/synchronization- problems
  112. 112. Синхронизация • The Little Book of Semaphores
 Allen B. Downey
 
 http://www.greenteapress.com/ semaphores/

×