Синхронизация состояний с использованием Mutex vs Channel в Go

Исходное сообщение Ссылка на сайт

Это одна из моих статей, которая заставила меня изучить весь Google в поисках того, какие методы лучше всего подходят для того, чтобы синхронизация работала хорошо в GoLang. Все это началось, когда я начал создавать свой собственный пакет GoLang, Go-Log. Это пакет ведения журнала, который предоставляет утилиту поверх обычного пакета журнала Go с такими функциями, как — пометка журналов в вариант отладки и ошибки, добавление/удаление временной метки в журналах, а также получение сведений о вызывающей функции в журналах. Тем не менее, была большая необходимость сделать эту регистрацию потокобезопасный или вы можете было необходимость синхронизации поскольку, когда на сервер приходят миллионы запросов, логи нужно синхронизировать с меньшей задержкой.

Просматривая статьи, вопросы и ответы StackOverflow, видео в идиоматическом стиле Go, я наткнулся на два метода:

  1. Координация с каналами, которые уже являются потокобезопасными
  2. Координация использования Mutex в общей памяти

Самая распространенная ошибка Go-разработчика?

Прежде чем приступить к обсуждению того, какой метод выбрать, вам всем нужно знать распространенную ошибку Go-разработчика, которую вы все совершаете. Я знаю, что вы все фантазируете о шаблоне параллелизма, который заставляет вас чрезмерно использовать суперсилу Go — каналы и горутины, что в конце концов становится анти-паттерном. Я не говорю, что каналы плохие или их нельзя использовать для синхронизации, но я говорю о чрезмерном использовании. (используя его там, где нет необходимости) это определенно не тот путь, которому вы должны следовать.


Дэйв Чейни, участник проекта с открытым кодом и язык программирования Go, однажды в интервью сказал: «Я пытался использовать каналы для всего, если вы хотите говорить о худшем коде».


В официальной документации Go говорится, что «распространенной ошибкой новичков в Go является чрезмерное использование каналов и горутин только потому, что это возможно и/или потому, что это весело».


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

Связь с использованием каналов для достижения синхронизации

каналы — это каналы, которые соединяют параллельные горутины. Вы можете отправлять значения в каналы из одной горутины и получать эти значения в другую горутину.

Каналы лучше всего подходят в таких случаях, как передача прав собственности на данные, распределение единиц работы и передача асинхронных результатов.

Давайте воспользуемся этими каналами для синхронизации моего пакета Go Lang (цель состоит в том, чтобы журналы работали синхронно и потокобезопасно). Ниже приведен фрагмент кода из моего пакета, который я написал ранее.

Я использовал базовую коммуникацию по каналам для синхронизации нескольких горутин, что может произойти, когда журналы разъединяются миллион раз. Лучшее в каналах то, что они имеют встроенную безопасность потоков и предотвращают состояние гонки.

Если внимательно посмотреть на мой случай и спросить, была ли для этого определенная необходимость в каналах? Ответ НЕТ. Каналы — это концепция высокого уровня в Go, которая где-то внутри использует только Mutex. Каналы Go привлекательны, поскольку они обеспечивают встроенную безопасность потоков и поощряют однопоточный доступ к общим критически важным ресурсам. Каналы, однако, несут потери производительности по сравнению с мьютексами. Использование мьютексов полезно, когда вам просто нужны блокировки для нескольких общих ресурсов. Не бойтесь использовать sync.Mutex если это лучше всего подходит для вашей проблемы.

Как я использовал Mutex для синхронного логирования?

Мьютекс (блокировка взаимного исключения) — бесценный ресурс при синхронизации состояния между несколькими горутинами, но я считаю, что его использование несколько загадочно для новых разработчиков Go. Это довольно легко использовать!

Вот фрагмент кода из моего пакета, Go-Log

Я использовал mutex.Lock() и mutex.Unlock() для создания синхронной блокировки общего ресурса. А для управления несколькими логами я каждый раз создаю горутину и добавляю их в sync.WaitGroup. Это важный примитив синхронизации. Это позволяет взаимодействующим горутинам коллективно ожидать порогового события, прежде чем снова продолжить независимо друг от друга.

В нашем случае этот подход гораздо лучше и быстрее! Мы сократили ненужные накладные расходы. Однако, если вы когда-нибудь обнаружите, что ваши правила блокировки sync.Mutex становятся слишком сложными, спросите себя, может ли использование каналов быть проще.

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

MindorksOpenSource/Go-Log
_Пакет журнала Go, который предоставляет утилиту поверх обычного пакета журнала Go. — MindorksOpenSource/Go-Log_github.com


Дополнительные ресурсы

Закрытие
_23 января 2016 г. Сообщество — «Поделитесь памятью, общаясь» Интерпретация — «КАНАЛИЗИРУЙТЕ ВСЕ ЭТО THINGZ!» Потому что многие…_www.acloudtree.com

расти/до
_Язык программирования Go. Внесите свой вклад в разработку golang/go, создав учетную запись на GitHub._github.com.

Найди меня!

Твиттер: https://twitter.com/DuaYashish
НаставникКруиз:

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *