Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Задачи синхронизации: классические и прикладные решения

Faf4a633b0d1e32a07a071039686c868?s=47 Egor Tolstoy
September 28, 2015

Задачи синхронизации: классические и прикладные решения

Выступление на Rambler.iOS #4:
Видео: http://www.youtube.com/watch?v=y0UQEioIgTQ
Исходники: https://github.com/rambler-digital-solutions/synchronization-problems

Faf4a633b0d1e32a07a071039686c868?s=128

Egor Tolstoy

September 28, 2015
Tweet

Transcript

  1. Егор Толстой Ведущий iOS разработчик @ Rambler&Co Задачи синхронизации Классические

    и прикладные решения
  2. Синхронизация • Что такое синхронизация • Решение проблем синхронизации •

    Классические задачи синхронизации
  3. Синхронизация • Синхронизация - 
 обеспечение правильной совместной работы нескольких

    потоков.
  4. Синхронизация Алиса Боб Поток 1 Поток 2

  5. Синхронизация Алиса Боб Поток 1 Поток 2

  6. Синхронизация Алиса Боб Поток 1 Поток 2

  7. Синхронизация Алиса Боб Поток 1 Поток 2

  8. Синхронизация • Состояние гонки - 
 работа приложения зависит от

    последовательности вызова секции его кода разными потоками.
  9. Синхронизация func incrementSharedVariable { // counter == 0 counter +=

    1 }
  10. Синхронизация func incrementSharedVariable { // counter == 0 counter +=

    1 } Поток 1 Поток 2 Поток 3
  11. Синхронизация func incrementSharedVariable { // counter == 0 counter +=

    1 } Поток 1 Поток 2 Поток 3 counter ∈ [1,3]
  12. Синхронизация • Критическая секция - 
 участок кода, в котором

    одновременно может находиться только один поток.
  13. Синхронизация func incrementSharedVariable { lockSection() counter += 1 unlockSection() }

  14. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable {

    lockSection() counter += 1 unlockSection() }
  15. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable {

    lockSection() counter += 1 unlockSection() }
  16. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable {

    lockSection() counter += 1 unlockSection() }
  17. Синхронизация Поток 1 Поток 2 Поток 3 func incrementSharedVariable {

    lockSection() counter += 1 unlockSection() } counter == 3
  18. Синхронизация • Deadlock - 
 несколько потоков блокируют выполнение друг

    друга.
  19. Синхронизация • У каждой задачи синхронизации есть определенные условия.

  20. Синхронизация Алиса Боб Поток 1 Поток 2

  21. Синхронизация Алиса Боб Поток 1 Поток 2

  22. Синхронизация Алиса Боб Поток 1 Поток 2

  23. Синхронизация Алиса Боб Поток 1 Поток 2

  24. Синхронизация • Передача сообщений между потоками - простое решение большинства

    проблем.
  25. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть

    обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3
  26. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть

    обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3
  27. Синхронизация Алиса Боб а1: Съесть завтрак а2: Поработать а3: Съесть

    обед а4: Позвонить Бобу б1: Съесть завтрак б2: Дождаться звонка Алисы б3: Съесть обед а1 < a2 < a3 < a4 б1 < б2 < б3 б3 > б2 > a4 > a3
  28. Синхронизация • События считаются параллельными, если, изучив код программы, мы

    не можем утверждать, какое из них произойдет первым.
  29. Синхронизация 0 Алиса Семафор Боб

  30. Синхронизация 0 Алиса Семафор Боб

  31. Синхронизация wait 0 Алиса Семафор Боб

  32. Синхронизация wait -1 Алиса Семафор Боб

  33. Синхронизация wait -1 Алиса Семафор Боб

  34. Синхронизация signal wait -1 Алиса Семафор Боб

  35. Синхронизация signal wait 0 Алиса Семафор Боб

  36. Синхронизация signal wait 0 Алиса Семафор Боб

  37. Синхронизация • Семафор создается с начальным значением, • wait -

    уменьшает счетчик, • signal - увеличивает счетчик.
  38. Синхронизация • Задача "Читатели-Писатели" 
 Readers-Writers problem

  39. Синхронизация • Любое количество читателей в критической секции • Единственный

    писатель в критической секции
  40. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели

    0
  41. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели

    0
  42. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели

    0
  43. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели

    0
  44. Синхронизация 1. Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели

    0
  45. Синхронизация 0. Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели

    1
  46. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2

    0.
  47. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2

    -1.
  48. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2

    -1.
  49. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2

    -1.
  50. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 2

    -1.
  51. Синхронизация Семафор "комната пуста" on Выключатель "читатели" Читатели Писатели 1

    -1.
  52. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0

    0.
  53. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0

    0.
  54. Синхронизация Семафор "комната пуста" off Выключатель "читатели" Читатели Писатели 0

    1.
  55. Синхронизация • Голод - состояние, в котором поток может бесконечно

    ждать своей очереди. 
 А может и дождаться.
  56. Синхронизация • Решение с использованием NSOperation

  57. Синхронизация class OperationScheduler { var readerQueue = NSOperationQueue() var writerQueue

    = NSOperationQueue() init () { // Читатели должны выполняться параллельно readerQueue.maxConcurrentOperationCount = MAX // Писатели должны выполняться последовательно writerQueue.maxConcurrentOperationCount = 1 } ... }
  58. Синхронизация func addReaderOperation(operation: NSBlockOperation) { // Зависим от выполнения всех

    писателей for writerOperation in writerQueue.operations { operation.addDependency(writerOperation) } readerQueue.addOperation(operation) }
  59. Синхронизация func addWriterOperation(operation: NSBlockOperation) { // Все читатели зависят от

    нового писателя for readerOperation in readerQueue.operations { readerOperation.addDependency(operation) } writerQueue.addOperation(operation) }
  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. Синхронизация • Задача "Обедающие философы" 
 Dining philosophers problem

  62. Синхронизация while(true) { think() getForks() eat() putForks() }

  63. Синхронизация • Не больше одного философа на вилку • Не

    допустить deadlock • Не допустить голод
  64. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 1 вилка 1

    вилка 1 вилка 1 вилка 1
  65. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0

    вилка 0 вилка 0 вилка 0
  66. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0

    вилка 0 вилка 0 вилка 0
  67. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0

    вилка 0 вилка 0 вилка 0
  68. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 вилка 0 вилка 0

    вилка 0 вилка 0 вилка 0 deadlock :(
  69. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 4 вилка

    1 вилка 1 вилка 1 вилка 1 вилка 1
  70. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 3 вилка

    1 вилка 1 вилка 1 вилка 1 вилка 1
  71. Синхронизация Ф.5 Ф.1 Ф.2 Ф.3 Ф.4 Семафор "официант" 3 вилка

    0 вилка 1 вилка 0 вилка 1 вилка 1
  72. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка вилка 0 вилка

    1 вилка 1 Ф.2 Семафор "официант" 2 Ф.1 1
  73. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 1 вилка 1 Ф.2 Семафор "официант" 2 Ф.1
  74. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 1 вилка 1 Ф.2 Семафор "официант" 1 Ф.1
  75. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 0 вилка 1 Ф.2 Семафор "официант" 1 Ф.1
  76. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 0 вилка 1 Ф.2 Семафор "официант" 0 Ф.1
  77. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 0 вилка 0 Ф.2 Семафор "официант" 0 Ф.1
  78. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 1

    вилка 0 вилка 0 Ф.2 Семафор "официант" 1 Ф.1
  79. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 0 вилка 0 Ф.2 Семафор "официант" 0 Ф.1
  80. Синхронизация Ф.5 Ф.3 Ф.4 вилка 1 вилка 0 вилка 0

    вилка 0 вилка 0 Ф.2 Семафор "официант" 1 Ф.1
  81. Синхронизация Ф.5 Ф.3 Ф.4 вилка 0 вилка 0 вилка 0

    вилка 0 вилка 0 Ф.2 Семафор "официант" 0 Ф.1
  82. Синхронизация • Решение с использованием NSOperation

  83. Синхронизация class DiningPhilosophersOperationScheduler { var philosopherQueues = [NSOperationQueue]() init() {

    for _ in 0...4 { let philosopherQueue = NSOperationQueue() philosopherQueue.maxConcurrentOperationCount = 1 philosopherQueues.append(philosopherQueue) } } ... }
  84. Синхронизация class PhilosopherBlockOperation: NSBlockOperation { init(index: Int) { super.init() addExecutionBlock({

    print("philosopher \(index) is eating") sleep(2) print("philosopher \(index) puts forks") }) } }
  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. Синхронизация 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. Синхронизация > 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. Синхронизация • Задача "Собираем H2O" 
 Building H2O problem

  89. Синхронизация • Кислород ждет двух потоков водорода • Водород ждет

    одного потока водорода и одного - кислорода
  90. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер
  91. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О
  92. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О
  93. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О H
  94. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О H
  95. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3

    Барьер О H
  96. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3

    Барьер О H H
  97. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -1 3

    Барьер О H H
  98. Синхронизация -1 Семафор "Кислород" Кислород Водород Семафор "Водород" -2 3

    Барьер О H H
  99. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О H H
  100. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер О H H
  101. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 0

    Барьер О H H
  102. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 0

    Барьер О H H
  103. Синхронизация 0 Семафор "Кислород" Кислород Водород Семафор "Водород" 0 3

    Барьер
  104. Синхронизация • Решение с использованием NSOperation

  105. Синхронизация func triggerHydrogenEvent(location: CGPoint) { let sprite = AtomNode.atom(AtomSprite.Hydrogen, location:

    location) self.addChild(sprite) self.scheduler.addHydrogen(sprite, block: atomBlock(sprite)) }
  106. Синхронизация class H2OOperationScheduler { let moleculeQueue = NSOperationQueue() // Этот

    блок вызывается при успешном сборе молекулы H2O var moleculeBlock: (Array<SKSpriteNode>) -> Void init(H2OBlock: (Array<SKSpriteNode>) -> Void) { moleculeQueue.maxConcurrentOperationCount = 1 moleculeBlock = H2OBlock } ... }
  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. Синхронизация 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. Синхронизация class H2OOperation: NSOperation { ... override func main() {

    atomQueue.suspended = false atomQueue.waitUntilAllOperationsAreFinished() self.moleculeBlock(nodes) } ... }
  110. Синхронизация • Синхронизация - это непросто • Синхронизация - это

    интересно • Синхронизация - это важно
  111. Синхронизация • Код примеров:
 https://github.com/rambler- digital-solutions/synchronization- problems

  112. Синхронизация • The Little Book of Semaphores
 Allen B. Downey


    
 http://www.greenteapress.com/ semaphores/