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

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

Embed Size (px)

Citation preview

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

Егор Толстой Ведущий iOS разработчик @ Rambler&Co

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

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

Синхронизация

•Что такое синхронизация

•Решение проблем синхронизации

•Классические задачи синхронизации

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

Синхронизация

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

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

Синхронизация

Алиса

Боб

Поток 1 Поток 2

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

Синхронизация

Алиса Боб

Поток 1 Поток 2

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

Синхронизация

Алиса Боб

Поток 1 Поток 2

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

Синхронизация

Алиса

Боб

Поток 1 Поток 2

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

Синхронизация

•Состояние гонки - работа приложения зависит от последовательности вызова секции его кода разными потоками.

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

Синхронизация

func incrementSharedVariable { // counter == 0 counter += 1 }

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

Синхронизация

func incrementSharedVariable { // counter == 0 counter += 1 }

Поток 1 Поток 2 Поток 3

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

Синхронизация

func incrementSharedVariable { // counter == 0 counter += 1 }

Поток 1 Поток 2 Поток 3

counter ∈ [1,3]

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

Синхронизация

•Критическая секция - участок кода, в котором одновременно может находиться только один поток.

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

Синхронизация

func incrementSharedVariable { lockSection()

counter += 1 unlockSection()

}

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

Синхронизация

Поток 1 Поток 2 Поток 3

func incrementSharedVariable { lockSection()

counter += 1 unlockSection()

}

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

Синхронизация

Поток 1 Поток 2 Поток 3

func incrementSharedVariable { lockSection()

counter += 1 unlockSection()

}

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

Синхронизация

Поток 1 Поток 2 Поток 3

func incrementSharedVariable { lockSection()

counter += 1 unlockSection()

}

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

Синхронизация

Поток 1 Поток 2 Поток 3

func incrementSharedVariable { lockSection()

counter += 1 unlockSection()

}

counter == 3

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

Синхронизация

• Deadlock - несколько потоков блокируют выполнение друг друга.

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

Синхронизация

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

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

Синхронизация

Алиса Боб

Поток 1 Поток 2

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

Синхронизация

Алиса

Боб

Поток 1 Поток 2

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

Синхронизация

Алиса

Боб

Поток 1 Поток 2

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

Синхронизация

Алиса Боб

Поток 1 Поток 2

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

Синхронизация

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

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

Синхронизация

Алиса Боб

а1: Съесть завтрак

а2: Поработать

а3: Съесть обед

а4: Позвонить Бобу

б1: Съесть завтрак

б2: Дождаться звонка Алисы

б3: Съесть обед

а1 < a2 < a3 < a4 б1 < б2 < б3

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

Синхронизация

Алиса Боб

а1: Съесть завтрак

а2: Поработать

а3: Съесть обед

а4: Позвонить Бобу

б1: Съесть завтрак

б2: Дождаться звонка Алисы

б3: Съесть обед

а1 < a2 < a3 < a4 б1 < б2 < б3

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

Синхронизация

Алиса Боб

а1: Съесть завтрак

а2: Поработать

а3: Съесть обед

а4: Позвонить Бобу

б1: Съесть завтрак

б2: Дождаться звонка Алисы

б3: Съесть обед

а1 < a2 < a3 < a4 б1 < б2 < б3

б3 > б2 > a4 > a3

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

Синхронизация

•События считаются параллельными, если, изучив код программы, мы не можем утверждать, какое из них произойдет первым.

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

Синхронизация

0

Алиса

Семафор

Боб

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

Синхронизация

0

Алиса

Семафор

Боб

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

Синхронизация

wait0

Алиса

Семафор

Боб

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

Синхронизация

wait-1

Алиса

Семафор

Боб

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

Синхронизация

wait-1Алиса

Семафор

Боб

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

Синхронизация

signal wait-1Алиса

Семафор

Боб

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

Синхронизация

signal wait0Алиса

Семафор

Боб

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

Синхронизация

signal wait0

Алиса

Семафор

Боб

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

Синхронизация

•Семафор создается с начальным значением,

• wait - уменьшает счетчик,

• signal - увеличивает счетчик.

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

Синхронизация

•Задача "Читатели-Писатели" Readers-Writers problem

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

Синхронизация

•Любое количество читателей в критической секции

•Единственный писатель в критической секции

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

Синхронизация

1.

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

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

Синхронизация

1.

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

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

Синхронизация

1.

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

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

Синхронизация

1.

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

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

Синхронизация

1.

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

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

Синхронизация

0.

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

1

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

2

0.

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

2

-1.

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

2

-1.

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

2

-1.

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

2

-1.

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

Синхронизация

Семафор "комната пуста"

on

Выключатель "читатели"

Читатели Писатели

1

-1.

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

Синхронизация

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

0.

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

Синхронизация

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

0.

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

Синхронизация

Семафор "комната пуста"

off

Выключатель "читатели"

Читатели Писатели

0

1.

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

Синхронизация

• Голод - состояние, в котором поток может бесконечно ждать своей очереди. А может и дождаться.

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

Синхронизация

•Решение с использованием NSOperation

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

Синхронизация

class OperationScheduler { var readerQueue = NSOperationQueue() var writerQueue = NSOperationQueue() init () { // Читатели должны выполняться параллельно readerQueue.maxConcurrentOperationCount = MAX // Писатели должны выполняться последовательно writerQueue.maxConcurrentOperationCount = 1 }

... }

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

Синхронизация

func addReaderOperation(operation: NSBlockOperation) { // Зависим от выполнения всех писателей for writerOperation in writerQueue.operations { operation.addDependency(writerOperation) } readerQueue.addOperation(operation) }

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

Синхронизация

func addWriterOperation(operation: NSBlockOperation) { // Все читатели зависят от нового писателя for readerOperation in readerQueue.operations { readerOperation.addDependency(operation) } writerQueue.addOperation(operation) }

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

Синхронизация

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

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

Синхронизация

•Задача "Обедающие философы" Dining philosophers problem

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

Синхронизация

while(true) { think() getForks() eat() putForks() }

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

Синхронизация

•Не больше одного философа на вилку

•Не допустить deadlock

•Не допустить голод

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

вилка1

вилка

1

вилка 1 вилка

1

вилка1

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

deadlock :(

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

Семафор "официант"

4

вилка1

вилка

1

вилка 1 вилка

1

вилка1

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

Семафор "официант"

3

вилка1

вилка

1

вилка 1 вилка

1

вилка1

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

Синхронизация

Ф.5

Ф.1

Ф.2

Ф.3

Ф.4

Семафор "официант"

3

вилка0

вилка

1

вилка 0 вилка

1

вилка1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

вилка 0 вилка

1

вилка1

Ф.2

Семафор "официант"

2

Ф.1

1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

1

вилка1

Ф.2

Семафор "официант"

2

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

1

вилка1

Ф.2

Семафор "официант"

1

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка1

Ф.2

Семафор "официант"

1

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка1

Ф.2

Семафор "официант"

0

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

Ф.2

Семафор "официант"

0

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 1 вилка

0

вилка0

Ф.2

Семафор "официант"

1

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

Ф.2

Семафор "официант"

0

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка1

вилка

0

вилка 0 вилка

0

вилка0

Ф.2

Семафор "официант"

1

Ф.1

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

Синхронизация

Ф.5

Ф.3

Ф.4

вилка0

вилка

0

вилка 0 вилка

0

вилка0

Ф.2

Семафор "официант"

0

Ф.1

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

Синхронизация

•Решение с использованием NSOperation

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

Синхронизация

class DiningPhilosophersOperationScheduler { var philosopherQueues = [NSOperationQueue]() init() { for _ in 0...4 { let philosopherQueue = NSOperationQueue() philosopherQueue.maxConcurrentOperationCount = 1 philosopherQueues.append(philosopherQueue) } }

... }

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

Синхронизация

class PhilosopherBlockOperation: NSBlockOperation { init(index: Int) { super.init()

addExecutionBlock({ print("philosopher \(index) is eating") sleep(2) print("philosopher \(index) puts forks") }) } }

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

Синхронизация

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) }

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

Синхронизация

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

Page 87: Rambler.iOS #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

Ф.0

Ф.1

Ф.2

Ф.3Ф.4

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

Синхронизация

•Задача "Собираем H2O" Building H2O problem

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

Синхронизация

•Кислород ждет двух потоков водорода

•Водород ждет одного потока водорода и одного - кислорода

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

О

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

О

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

ОH

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

О H

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

-1

3Барьер

О H

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

-1

3Барьер

О HH

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

-1

3Барьер

О H H

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

Синхронизация

-1

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

-2

3Барьер

О H H

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

О H H

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

О H H

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

0Барьер

О H H

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

0Барьер

О H H

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

Синхронизация

0

Семафор "Кислород"

Кислород Водород

Семафор "Водород"

0

3Барьер

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

Синхронизация

•Решение с использованием NSOperation

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

Синхронизация

func triggerHydrogenEvent(location: CGPoint) { let sprite = AtomNode.atom(AtomSprite.Hydrogen, location: location) self.addChild(sprite) self.scheduler.addHydrogen(sprite, block: atomBlock(sprite)) }

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

Синхронизация

class H2OOperationScheduler { let moleculeQueue = NSOperationQueue() // Этот блок вызывается при успешном сборе молекулы H2O var moleculeBlock: (Array<SKSpriteNode>) -> Void init(H2OBlock: (Array<SKSpriteNode>) -> Void) { moleculeQueue.maxConcurrentOperationCount = 1 moleculeBlock = H2OBlock } ... }

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

Синхронизация

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) }

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

Синхронизация

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++ } }

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

Синхронизация

class H2OOperation: NSOperation { ...

override func main() { atomQueue.suspended = false atomQueue.waitUntilAllOperationsAreFinished() self.moleculeBlock(nodes) } ... }

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

Синхронизация

•Синхронизация - это непросто

•Синхронизация - это интересно

•Синхронизация - это важно

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

Синхронизация

•Код примеров:https://github.com/rambler-digital-solutions/synchronization-problems

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

Синхронизация

• The Little Book of Semaphores Allen B. Downeyhttp://www.greenteapress.com/semaphores/