awesome-everything EN
↑ Обратно к восхождению

Базовый CS с нуля

Время и конкурентность: чтение кода

Суть Читай небольшие сниппеты — головоломку порядка event loop, переплетение thread'ов, lost-update data race и фикс через lock — и предсказывай поведение или выбирай правильный фикс.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 14 min

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

Цель

Отработай ключевой навык этого юнита: трассировать, что когда выполняется. Предсказывай порядок вывода event loop, замечай, как два thread’а переплетаются над общим состоянием, распознавай lost-update data race и определяй lock, который его чинит, не перебарщивая.

Сниппет 1 — порядок event loop

console.log("start");

setTimeout(() => {
  console.log("timeout");   // callback
}, 0);

console.log("end");
Викторина

Что это печатает по порядку?

Сниппет 2 — два thread’а, одна общая переменная

shared: total = 0

Thread A:                  Thread B:
  r = read(total)            r = read(total)   // оба читают 0
  r = r + 1                  r = r + 1
  write(total, r)            write(total, r)   // оба пишут 1
Викторина

Оба thread'а выполняют это по разу, параллельно, на двух ядрах. После того как оба закончат, чем может быть total — и как это называется?

Сниппет 3 — тот же код под нагрузкой

total = 0
spawn 1000 threads, each does:  total = total + 1   // без synchronization
join all threads
print(total)
Викторина

На многоядерной машине каким будет вероятное напечатанное значение и почему?

Сниппет 4 — добавляем lock

total = 0
lock = new Lock()

each of 1000 threads does:
  lock.acquire()
  total = total + 1     // защищено: только один thread внутри за раз
  lock.release()
Викторина

Что меняет lock и какова цена?

Итог

Читать конкурентность — значит читать, когда что выполняется. Event loop ставит синхронный код первым, а callback’и последними (start, end, timeout). Когда работа разбита на thread’ы, делящие состояние, обычный total = total + 1 на деле read-add-write, поэтому параллельные thread’ы могут переплестись, прочитать одно значение и перезаписать друг друга — data race, теряющий обновления и дающий неверный недетерминированный итог. Lock чинит это, делая общую секцию неделимой: один thread за раз, точный результат восстановлен. Цена в том, что заблокированная секция выполняется последовательно. Зрелый ход — сохранить lock для корректности и сделать заблокированную область как можно меньше.

Продолжить восхождение ↑Время и конкурентность: воспроизведи и почини race
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.