Механизмы синхронизации процессов/потоков в UNIX/Linux
Какие Вы знаете механизмы синхронизации процессов/потоков в UNIX/Linux ? Вопрос с собеседования по С++ на позицию Software Developer
Ответы (1 шт):
Этот пост написан в постновогодней депрессии/подпитии, так что прошу не обессудьте за искренние эмоций/прямоту и если я что-то забыл.
Пройдёмся по классическим IPC:
Многие из этих вызовов доступно в двух эпостасях: BSD и SysV. Для большинства из таких примитивов на практике первые используются чаще; вторые есть во многих ОС; в основном по историческим соображениям.
Сигналы — работать с ними крайне геморройно в силу их асинхронности, так что почти наверняка, если в обработчике сигнала возникает необходимость сделать что-то кроме как установить какой-то флаг, то скорей всего это ошибка.
Трубы (каналы, fifo) — анонимные трубы (
man 2 pipe) применяются часто; именованные каналы (man 3 mkfifo), для передачи данных стороннему процессу — иногда допустимы, но создавать именованный канал для управления текущим — это, скорей всего, ошибка.Сокеты (в особенности
man 2 socketpairиman 7 unix) — это то что используется повсеместно.Очереди ожидания (
man 3 mq_openman 2 msgget) — используется чуть чаще чем никогда; скорей всего, если тебе не нужны приоритеты, то вместо этого тебе нужен сокет.Общая память (
man 2 mmap;man 2 shmget) — используется повсеместно; не то что бы является средством синхронизации в узком смысле, но не упомянуть нельзя.Семафоры (
man sem_open,man 2 semget) — см. что такое семафор; в рамках голого posix — незаменимы; на практике могут быть полезны для специфичных задач.Блокировки файлов (
man 2 flock,man lockf,man fcntl); внимание: блокировки почти всегда кооперативные, т.е. блокируют доступ к файлу, только если другой процесс также пытается получить блокировку.futex (
man 2 futex) — специфично для linux; используются в основном для реализации других примитивов.
Для межпоточной синхронизации есть также примитивы pthread:
Мьютекс (
man pthread_mutex)Условная переменная (
man pthread_cond_timedwait)Join'ы *(man pthread_join) — способ дождаться окончания потокаБарьеры (
man pthread_barrier_init)Спин-блокировки (
man pthread_spin_init)
Ну а ещё есть примитив из C++20:
- Ожидание на условной переменной. В linux оптимально реализуется средствами futex'а.