Многопоточность: программа и процесс
Разница между программой и процессом тонкая, но мы попробуем ее нащупать.
Программа - это набор инструкций, которые выполняют определенную задачу при выполнении компьютером, в то время как процесс является экземпляром выполняемой компьютерной программы. Таким образом, в этом главное отличие программы и процесса.
Кроме того, время жизни - еще одно важное различие между программой и процессом. Программа имеет более длительный срок службы, чем процесс.
На жестком диске хранятся программы, и этим программам не требуются ресурсы, в то время как процессам требуются такие ресурсы, как память, устройства ввода-вывода и процессор.
Программа и процесс - это два термина в операционных системах, таких как Linux и Windows. Основное различие между программой и процессом состоит в том, что программа - это набор инструкций, который позволяет ЦПУ выполнять определенную задачу, в то время как процесс - это исполняемая программа.
Разница между программой и процессом тонкая, но мы попробуем ее нащупать.
Программа - это набор инструкций, которые выполняют определенную задачу при выполнении компьютером, в то время как процесс является экземпляром выполняемой компьютерной программы. Таким образом, в этом главное отличие программы и процесса.
Кроме того, время жизни - еще одно важное различие между программой и процессом. Программа имеет более длительный срок службы, чем процесс.
На жестком диске хранятся программы, и этим программам не требуются ресурсы, в то время как процессам требуются такие ресурсы, как память, устройства ввода-вывода и процессор.
Программа и процесс - это два термина в операционных системах, таких как Linux и Windows. Основное различие между программой и процессом состоит в том, что программа - это набор инструкций, который позволяет ЦПУ выполнять определенную задачу, в то время как процесс - это исполняемая программа.
🔥6👍2
Многопоточность: InterProcess Communication (IPC)
Как я уже писал выше — процессы не могут взаимодействовать друг с другом. Но это не совсем верно.
InterProcess Communication — это механизм операционной системы, который позволяет процессам взаимодействовать друг с другом. Это взаимодействие может включать в себя процесс, сообщающий другому процессу, что произошло какое-то событие, или передачу данных от одного процесса к другому.
Во многих операционных системах он используется для большинства коммуникаций:
- сокеты общаются с другими процессами.
- Все POSIX ситемы делятся общей памятью
- Почти все операционные системы могут в запись на диск, или запись, синтезируемая по запросу файловым сервером, к которой могут обращаться несколько процессов.
https://www.tutorialspoint.com/what-is-inter-process-communication-ipc
Как я уже писал выше — процессы не могут взаимодействовать друг с другом. Но это не совсем верно.
InterProcess Communication — это механизм операционной системы, который позволяет процессам взаимодействовать друг с другом. Это взаимодействие может включать в себя процесс, сообщающий другому процессу, что произошло какое-то событие, или передачу данных от одного процесса к другому.
Во многих операционных системах он используется для большинства коммуникаций:
- сокеты общаются с другими процессами.
- Все POSIX ситемы делятся общей памятью
- Почти все операционные системы могут в запись на диск, или запись, синтезируемая по запросу файловым сервером, к которой могут обращаться несколько процессов.
https://www.tutorialspoint.com/what-is-inter-process-communication-ipc
👍5
Многопоточность: Проблема производителя и потребителя
Проблема «производитель-потребитель» — это классическая проблема синхронизации
Два процесса используют общий буфер фиксированного размера. Один из них, производитель, помещает информацию в буфер, а другой, потребитель, извлекает ее оттуда.
Проблемы возникают в тот момент, когда производителю требуется поместить новую запись в уже заполненный буфер.
Проблема «производитель-потребитель» — это классическая проблема синхронизации
Два процесса используют общий буфер фиксированного размера. Один из них, производитель, помещает информацию в буфер, а другой, потребитель, извлекает ее оттуда.
Проблемы возникают в тот момент, когда производителю требуется поместить новую запись в уже заполненный буфер.
👍2🔥1
Код выше добавляет и удаляет целое число 10 раз в массиве. Поскольку все эти вызовы выполняются параллельно, невозможно предсказать порядок их выполнения. Поскольку добавление и удаление происходят одновременно может быть сбой
Рассмотрим следующий сценарий:
1. Девять блоков add уже выполнены, осталось выполнить только один блок
2. Принимая во внимание, что все 8 блоков удаления выполняются, и в настоящее время выполняются последние два. Таким образом, в этот момент количество элементов будет равно 1
3. Из-за состояния гонки предположим, что последний блок добавления выполняется после двух блоков удаления.
В приведенном выше сценарии, поскольку количество элементов равно 1 и два блока удаления выполняются одновременно, вызов remove два раза для массива со значением 1 приведет к сбою.
Рассмотрим следующий сценарий:
1. Девять блоков add уже выполнены, осталось выполнить только один блок
2. Принимая во внимание, что все 8 блоков удаления выполняются, и в настоящее время выполняются последние два. Таким образом, в этот момент количество элементов будет равно 1
3. Из-за состояния гонки предположим, что последний блок добавления выполняется после двух блоков удаления.
В приведенном выше сценарии, поскольку количество элементов равно 1 и два блока удаления выполняются одновременно, вызов remove два раза для массива со значением 1 приведет к сбою.
👍5🔥2❤1
«Атомные привычки»
Уровень воды: 40%
Оценка: 4/5
Буду иногда публиковать сюда рецензии на книги, которые читаю для профессионального развития.
Трудно заметить, что книга не про иос. И ты не ошибёшься. Она о процессе развития. «Атомные привычки» — книга популярная не только в бизнес индустрии, но и можно встретить рекомендацию у ит инфлюенсеров.
Все мы состоим из привычек. Унаследовали их от семьи, коллег, друзей. Эти привычки и определяют наше развитие.
В книге много советов как выработать свою систему по их формированию. Делать привлекательней полезные, и избавляться от вредных.
Подойдёт для укрепления дисциплины ежедневно решать литкод задачи 🙂
Уровень воды: 40%
Оценка: 4/5
Буду иногда публиковать сюда рецензии на книги, которые читаю для профессионального развития.
Трудно заметить, что книга не про иос. И ты не ошибёшься. Она о процессе развития. «Атомные привычки» — книга популярная не только в бизнес индустрии, но и можно встретить рекомендацию у ит инфлюенсеров.
Все мы состоим из привычек. Унаследовали их от семьи, коллег, друзей. Эти привычки и определяют наше развитие.
В книге много советов как выработать свою систему по их формированию. Делать привлекательней полезные, и избавляться от вредных.
Подойдёт для укрепления дисциплины ежедневно решать литкод задачи 🙂
👍16
Многопоточность: Решение проблемы производителя и потребителя с помощью NSLock
Приведенный выше код блокирует выполнение других потоков всякий раз, когда элементы изменяются. Таким образом, всякий раз, когда блок выполняется, блокировка гарантирует, что ни один другой блок не будет задействован для выполнения, и, следовательно, делает приведенный выше код потокобезопасным.
Приведенный выше код использует
Приведенный выше код блокирует выполнение других потоков всякий раз, когда элементы изменяются. Таким образом, всякий раз, когда блок выполняется, блокировка гарантирует, что ни один другой блок не будет задействован для выполнения, и, следовательно, делает приведенный выше код потокобезопасным.
Приведенный выше код использует
defer
в remove
. Он используется, потому что defer вызывается перед выходом из функции. Поскольку remove имеет два пути выхода, репликация lock.unlock() в двух местах не рекомендуется. Следовательно, в этом случае defer полезен.👍5
Многопоточность: Примитив синхронизации Semaphore🚦
Семафоры помогают управлять доступом к общему ресурсу нескольким потокам.
Семафор состоит из очереди потоков и значения счетчика.
ℹ️Очередь потоков используется семафором для отслеживания ожидающих потоков в порядке FIFO
ℹ️Значение счетчика используется семафором, чтобы решить, должен ли поток получить доступ к общему ресурсу или нет. Значение счетчика изменяется, когда мы вызываем функцию signal() или wait().
Когда мы должны вызывать функции wait() и signal()?
- Вызов wait() нужен каждый раз перед использованием общего ресурса. По сути, мы спрашиваем семафор, доступен ли общий ресурс или нет. Если нет, будем ждать.
- Вызов signal() нужен каждый раз после использования общего ресурса. По сути, мы сигнализируем семафору, что закончили взаимодействие с общим ресурсом.
🚧 НИКОГДА не запускайте функцию семафора wait() в основном потоке, так как это приведет к зависанию вашего приложения.
Семафоры помогают управлять доступом к общему ресурсу нескольким потокам.
Семафор состоит из очереди потоков и значения счетчика.
ℹ️Очередь потоков используется семафором для отслеживания ожидающих потоков в порядке FIFO
ℹ️Значение счетчика используется семафором, чтобы решить, должен ли поток получить доступ к общему ресурсу или нет. Значение счетчика изменяется, когда мы вызываем функцию signal() или wait().
Когда мы должны вызывать функции wait() и signal()?
- Вызов wait() нужен каждый раз перед использованием общего ресурса. По сути, мы спрашиваем семафор, доступен ли общий ресурс или нет. Если нет, будем ждать.
- Вызов signal() нужен каждый раз после использования общего ресурса. По сути, мы сигнализируем семафору, что закончили взаимодействие с общим ресурсом.
🚧 НИКОГДА не запускайте функцию семафора wait() в основном потоке, так как это приведет к зависанию вашего приложения.
👍8
Многопоточность: Примитив синхронизации Mutex
Mutex — примитив синхронизации, что также захватывает ресурс. Как только поток пытается обратиться к ресурсу, захваченному мьютексом, никакой другой поток не сможет с ним взаимодействовать до тех пор, пока текущий поток не освободит этот ресурс
Стоит отметить, что mutex работает по принципу FIFO, то есть потоки будут захватывать ресурс по освобождению в том порядке, в котором данные потоки обратились к ресурсу.
Mutex подобен Lock. Разница в том, что это могут быть разные процессы, а не только треды. К сожалению, вам придется реализовать свой собственный Mutex, поскольку Swift его не поддерживает. Это можно сделать с помощью pthread_mutex от C.
Mutex — примитив синхронизации, что также захватывает ресурс. Как только поток пытается обратиться к ресурсу, захваченному мьютексом, никакой другой поток не сможет с ним взаимодействовать до тех пор, пока текущий поток не освободит этот ресурс
Стоит отметить, что mutex работает по принципу FIFO, то есть потоки будут захватывать ресурс по освобождению в том порядке, в котором данные потоки обратились к ресурсу.
Mutex подобен Lock. Разница в том, что это могут быть разные процессы, а не только треды. К сожалению, вам придется реализовать свой собственный Mutex, поскольку Swift его не поддерживает. Это можно сделать с помощью pthread_mutex от C.
👍5
Mutex vs Semaphore
Можно рассматривать двоичный семафор (семафор со значением счетчика 0 или 1) как Mutex. Но в то время как Mutex связан с механизмом блокировки, семафор является сигнальным механизмом. Это особо не помогает, так где же разница?
Механизм блокировки — это защита и управление доступом к ресурсу. Таким образом, он предотвращает одновременное обращение нескольких тредов к одному ресурсу. Сигнальная система больше напоминает вызов «Эй, я закончил! Продолжай!». Например, если вы слушаете музыку на своем мобильном телефоне и вам звонят, общий ресурс (наушники) будет задействован на телефоне. Когда звонок закончится, система проинформирует ваш mp3-плеер при помощи сигнала для продолжения. Это тот случай, когда следует предпочесть семафор мьютексу.
Так в чем же фишка? Представьте, что у вас есть тред с низким приоритетом (1), который находится в защищенной области, и у вас есть тред с высоким приоритетом (2), который просто вызывает wait() на семафоре. 2 спит и ждет, когда семафор разбудит его. Теперь у нас есть тред (3), который имеет более высокий приоритет, чем 1. Этот тред в сочетании с QoS блокирует сигнал от 1 к семафору и, таким образом, голодают оба других потока. Таким образом, семафоры в iOS не имеют приоритетного наследования (Priority Inheritance).
приложу ваши любимые видосы с объяснением от индусов
https://www.youtube.com/watch?v=8wcuLCvMmF8
Можно рассматривать двоичный семафор (семафор со значением счетчика 0 или 1) как Mutex. Но в то время как Mutex связан с механизмом блокировки, семафор является сигнальным механизмом. Это особо не помогает, так где же разница?
Механизм блокировки — это защита и управление доступом к ресурсу. Таким образом, он предотвращает одновременное обращение нескольких тредов к одному ресурсу. Сигнальная система больше напоминает вызов «Эй, я закончил! Продолжай!». Например, если вы слушаете музыку на своем мобильном телефоне и вам звонят, общий ресурс (наушники) будет задействован на телефоне. Когда звонок закончится, система проинформирует ваш mp3-плеер при помощи сигнала для продолжения. Это тот случай, когда следует предпочесть семафор мьютексу.
Так в чем же фишка? Представьте, что у вас есть тред с низким приоритетом (1), который находится в защищенной области, и у вас есть тред с высоким приоритетом (2), который просто вызывает wait() на семафоре. 2 спит и ждет, когда семафор разбудит его. Теперь у нас есть тред (3), который имеет более высокий приоритет, чем 1. Этот тред в сочетании с QoS блокирует сигнал от 1 к семафору и, таким образом, голодают оба других потока. Таким образом, семафоры в iOS не имеют приоритетного наследования (Priority Inheritance).
приложу ваши любимые видосы с объяснением от индусов
https://www.youtube.com/watch?v=8wcuLCvMmF8
YouTube
Semaphore Vs. Mutex - A Clear Understanding
Here you go.. The clear differences between Semaphore and Mutex. All the technical aspects are discussed with examples for each.
🔥3👍1
Grand Central Dispatch
Dispatch, больше известный как GCD – фреймворк, содержащий в себе языковые конструкции, позволяющие нам комфортно и достаточно просто управлять потоками, задачами для выполнения и ресурсами, которые нам необходимо захватить. GCD работает на системном уровне, таким образом он может удовлетворить потребности всех запущенных приложений на девайсе, при этом управляя ресурсами эффективно.
GCD реализован на языке C, поэтому фактически является низкоуровневым фреймворком.
Queue
Queue (очередь) – является основным примитивом GCD. Очередь представляет собой сущность, выполняющую задачи, поступающие на вход, на одном или множестве потоков. Представьте себе очередь на кассу в любом продуктовом магазине. В данном случае касса, которая вас обслужит – это поток, вы – сама задача, а все вместе – очередь.
Очередь работает по принципу FIFO, таким образом первая задача на очереди будет первой направлена на выполнение на потоке.
Dispatch, больше известный как GCD – фреймворк, содержащий в себе языковые конструкции, позволяющие нам комфортно и достаточно просто управлять потоками, задачами для выполнения и ресурсами, которые нам необходимо захватить. GCD работает на системном уровне, таким образом он может удовлетворить потребности всех запущенных приложений на девайсе, при этом управляя ресурсами эффективно.
GCD реализован на языке C, поэтому фактически является низкоуровневым фреймворком.
Queue
Queue (очередь) – является основным примитивом GCD. Очередь представляет собой сущность, выполняющую задачи, поступающие на вход, на одном или множестве потоков. Представьте себе очередь на кассу в любом продуктовом магазине. В данном случае касса, которая вас обслужит – это поток, вы – сама задача, а все вместе – очередь.
Очередь работает по принципу FIFO, таким образом первая задача на очереди будет первой направлена на выполнение на потоке.
🔥6
Queue
Говоря об очередях, очень хочется заострить внимание на следующем. Очередь (queue) и поток(thread) – не одно и то же. Очередь использует поток или несколько потоков для выполнения поступающих к ней задач.
Очереди делятся на 2 типа:
1️⃣ - serial (последовательная) – выполняет задачи последовательно (поочередно). До тех пор, пока задача не будет выполнена, поток не приступит к выполнения следующей задачи в очереди.
2️⃣ - concurrent (параллельная) – выполняет задачи параллельно. Задачи, поступающие в concurrent очередь, могут выполняться одновременно на разных потоках.
Говоря об очередях, очень хочется заострить внимание на следующем. Очередь (queue) и поток(thread) – не одно и то же. Очередь использует поток или несколько потоков для выполнения поступающих к ней задач.
Очереди делятся на 2 типа:
1️⃣ - serial (последовательная) – выполняет задачи последовательно (поочередно). До тех пор, пока задача не будет выполнена, поток не приступит к выполнения следующей задачи в очереди.
2️⃣ - concurrent (параллельная) – выполняет задачи параллельно. Задачи, поступающие в concurrent очередь, могут выполняться одновременно на разных потоках.
🔥8
Синхронное и асинхронное выполнение заданий
Как только очередь (queue) создана, задание на ней можно разместить с помощью двух функций:
1️⃣ sync — синхронное выполнение по отношению к текущей очереди
2️⃣ async — асинхронное выполнение по отношению к текущей очереди.
Синхронная функция sync возвращает управление на текущую очередь только после полного завершения задания, тем самым блокируя текущую очередь
Асинхронная функция async, в противоположность функции sync, возвращает управление на текущую очередь немедленно после запуска задания на выполнение в другой очереди, не ожидая его завершения. Таким образом, асинхронная функция async не блокирует выполнение заданий на текущей очереди
Как только очередь (queue) создана, задание на ней можно разместить с помощью двух функций:
1️⃣ sync — синхронное выполнение по отношению к текущей очереди
2️⃣ async — асинхронное выполнение по отношению к текущей очереди.
Синхронная функция sync возвращает управление на текущую очередь только после полного завершения задания, тем самым блокируя текущую очередь
Асинхронная функция async, в противоположность функции sync, возвращает управление на текущую очередь немедленно после запуска задания на выполнение в другой очереди, не ожидая его завершения. Таким образом, асинхронная функция async не блокирует выполнение заданий на текущей очереди
Какое поведение тут ожидается?
Anonymous Quiz
27%
Все будет нормально
4%
Произойдет ошибка компиляции
64%
Deadlock
4%
LiveLock
2%
Ничего не вызовется
Отдохнем немного от многопоточности.
В проектах начинающих разработчиков часто встречаю синглтоны. Есть много споров антипаттер ли одиночка или нет. Юзать его — ваша ответственность. Критично же юзать и не знать какие риски на себя берешь. Поэтому вкратце:
1. Синглтон нарушает SRP (Single Responsibility Principle) — класс синглтона, помимо того чтобы выполнять свои непосредственные обязанности, занимается еще и контролированием количества своих экземпляров.
2. Глобальное состояние. Про вред глобальных переменных вроде бы уже все знают, но тут та же самая проблема. Когда мы получаем доступ к экземпляру класса, мы не знаем текущее состояние этого класса, и кто и когда его менял, и это состояние может быть вовсе не таким, как ожидается.
3. Проблема тестирования. Вы не можете имитировать (mock away) синглтон при тестировании компонентов, использующих его. Это делает почти невозможным корректное модульное тестирование, потому что вы не добьётесь полной изоляции тестируемого кода.
есть неплохая статья, которая описывает все риски использования синглотона и его альтернативы
В проектах начинающих разработчиков часто встречаю синглтоны. Есть много споров антипаттер ли одиночка или нет. Юзать его — ваша ответственность. Критично же юзать и не знать какие риски на себя берешь. Поэтому вкратце:
1. Синглтон нарушает SRP (Single Responsibility Principle) — класс синглтона, помимо того чтобы выполнять свои непосредственные обязанности, занимается еще и контролированием количества своих экземпляров.
2. Глобальное состояние. Про вред глобальных переменных вроде бы уже все знают, но тут та же самая проблема. Когда мы получаем доступ к экземпляру класса, мы не знаем текущее состояние этого класса, и кто и когда его менял, и это состояние может быть вовсе не таким, как ожидается.
3. Проблема тестирования. Вы не можете имитировать (mock away) синглтон при тестировании компонентов, использующих его. Это делает почти невозможным корректное модульное тестирование, потому что вы не добьётесь полной изоляции тестируемого кода.
есть неплохая статья, которая описывает все риски использования синглотона и его альтернативы
Хабр
Синглтоны и общие экземпляры
Каждый раз при обсуждении программного обеспечения с другими разработчиками всплывает тема синглтонов, особенно в контексте развития WordPress’а. Я часто пытаюсь объяснить, почему их надо избегать,...
👍13❤2
Современные операционные системы | Таненбаум Эндрю, Бос Херберт
Уровень воды: 40%
Оценка: 5/5
Супер жесткая книга, которую буду еще много раз перечитывать и возвращаться. Однажды на собесах заметил, что ограничиваясь только платформой и инструментами упускаю банальные вещи работы с многопоточкой или памятью в наших системах.
Эту книгу много раз советовали, но наше знакомство же состоялось с темой многопоточки. Здесь много полезнейших вещей (которые, если честно, не очень легко написаны)
Советую каждому. От новичков до опытных.
Уровень воды: 40%
Оценка: 5/5
Супер жесткая книга, которую буду еще много раз перечитывать и возвращаться. Однажды на собесах заметил, что ограничиваясь только платформой и инструментами упускаю банальные вещи работы с многопоточкой или памятью в наших системах.
Эту книгу много раз советовали, но наше знакомство же состоялось с темой многопоточки. Здесь много полезнейших вещей (которые, если честно, не очень легко написаны)
Советую каждому. От новичков до опытных.
🔥11👍4
Хотел след пост о дедлоке запушить, но не смог не поделиться шедевральной статьей-переводом
Базовые принципы разработчика в гениальной простейшей форме
https://habr.com/ru/post/673640/
Базовые принципы разработчика в гениальной простейшей форме
https://habr.com/ru/post/673640/
Хабр
Разработчик с мозгом груга
Введение это сборник мыслей о разработке программ собранный разработчиком с мозгом груга разработчик с мозгом груга не очень умный, но разработчик с мозгом груга программирует много лет и научился кое...
🔥11💩3
Почему DispatchQueue.sync приводит к deadlock?
Для начала разберемся кто это вообще такой ваш мертвый замок. Представим ситуацию в ресторане. Повар спрашиваетповара официанта какой суп готовить, а официант отвечает, что скажет, только когда приготовишь суп.
Код выше обязательно придет к сбою. Очередь выполняет код синхронно. Второй клоужер не может запуститься, пока первый не закончится. Первый же клоужер не может выполниться, пока второй не запустится.
Для начала разберемся кто это вообще такой ваш мертвый замок. Представим ситуацию в ресторане. Повар спрашивает
Код выше обязательно придет к сбою. Очередь выполняет код синхронно. Второй клоужер не может запуститься, пока первый не закончится. Первый же клоужер не может выполниться, пока второй не запустится.
👍11
Проблема читателей-писаталей и барьер
Одна из самых частых задач на многопоточку. Чаще этой задачи на собесах никакую другую не повстречаешь. Почему? Потому что в любой статье или книге эту задачу каким-то боком да затрагивают.
Ее можно решить разными путями, но разберем самый подходящий.
Барьер — это механизм синхронизации потоков, который позволяет блокировать любое количество потоков до тех пор, пока ожидаемое количество потоков не достигнет барьера
Одна из самых частых задач на многопоточку. Чаще этой задачи на собесах никакую другую не повстречаешь. Почему? Потому что в любой статье или книге эту задачу каким-то боком да затрагивают.
Ее можно решить разными путями, но разберем самый подходящий.
Барьер — это механизм синхронизации потоков, который позволяет блокировать любое количество потоков до тех пор, пока ожидаемое количество потоков не достигнет барьера
В GCD есть свой механизм барьеров.
Барьеры GCD делают одну интересную вещь — они заставляют очередь временно не начинать новые задачи и ждут, пока все работающие в очереди задачи закончат свою работу, а затем выполняют свое замыкание.
Как только барьер начинает выполнять свое замыкание, он обеспечивает, чтобы очередь не выполняла никакие другие замыкания в течение этого времени и по существу работает как синхронная функция. Как только замыкание с барьером заканчивается, очередь возвращается к своей обычной работе, обеспечивая гарантию того, что никакая запись не будет проводиться одновременно с чтением или другой запись
Барьеры GCD делают одну интересную вещь — они заставляют очередь временно не начинать новые задачи и ждут, пока все работающие в очереди задачи закончат свою работу, а затем выполняют свое замыкание.
Как только барьер начинает выполнять свое замыкание, он обеспечивает, чтобы очередь не выполняла никакие другие замыкания в течение этого времени и по существу работает как синхронная функция. Как только замыкание с барьером заканчивается, очередь возвращается к своей обычной работе, обеспечивая гарантию того, что никакая запись не будет проводиться одновременно с чтением или другой запись
👍2