<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Celso Costa</title>
    <description>The latest articles on DEV Community by Celso Costa (@jccl).</description>
    <link>https://dev.to/jccl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1821045%2F5a98341f-7375-4805-b580-fe8818ac3d1b.png</url>
      <title>DEV Community: Celso Costa</title>
      <link>https://dev.to/jccl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jccl"/>
    <language>en</language>
    <item>
      <title>[Projeto] - Desenvolvimento de um Marketplace</title>
      <dc:creator>Celso Costa</dc:creator>
      <pubDate>Wed, 24 Jul 2024 21:41:43 +0000</pubDate>
      <link>https://dev.to/jccl/projeto-desenvolvimento-de-um-marketplace-14n8</link>
      <guid>https://dev.to/jccl/projeto-desenvolvimento-de-um-marketplace-14n8</guid>
      <description>&lt;h2&gt;
  
  
  Descrição do Projeto
&lt;/h2&gt;

&lt;p&gt;Desenvolvendo um marketplace. Como único desenvolvedor, fiquei responsável por desenvolver tanto o frontend quanto o backend, além de gerenciar a infraestrutura em uma VPS para colocar o sistema em produção. Estamos utilizando o padrão REST para a comunicação entre o frontend e o backend, bem como entre os serviços internos. Nosso objetivo é que esta primeira versão tenha funcionalidades essenciais, como registro e autenticação de usuários, listagem e gerenciamento de produtos, carrinho de compras, checkout e integração com um gateway de pagamento.&lt;/p&gt;

&lt;p&gt;O intuito deste post é mostrar como o projeto foi pensado e desenvolvido, apontar as dificuldades enfrentadas e, por fim, sugerir melhorias para as próximas versões. Caso você esteja pensando em construir um marketplace ou e-commerce, leve em consideração as informações contidas neste post, mas use o bom senso, pois nem tudo o que está aqui pode se aplicar ao seu caso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observação:&lt;/strong&gt; Esse post não irá detalhar como foi desenvolvido o frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisitos
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Definição:&lt;/strong&gt; Definem o que um sistema deve fazer e sob quais restrições. Requisitos relacionados com a primeira parte dessa definição - "o que um sistema deve fazer", ou seja, suas funcionalidades - são chamados de &lt;strong&gt;Requisitos Funcionais.&lt;/strong&gt; Já os requisitos relacionados a segunda parte - "sob que restrições" - são chamados de &lt;strong&gt;Requisitos Não Funcionais&lt;/strong&gt;.[1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requisitos Funcionais(RF)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Lojista&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;[RF01]: O sistema deve permitir que os lojistas se registrem sendo do tipo pessoa física ou jurídica.&lt;br&gt;
[RF02]: O sistema deve permitir que o administrador possa autorizar ou desautorizar o lojistas caso não esteja em conformidades com as informações verdadeiras informadas no cadastro.&lt;br&gt;
[RF03]: O sistema deve permitir que o lojista vincule o seu perfil a uma comunidade&lt;br&gt;
[RF04]: O sistema deve permitir que o lojista possa cria sua loja com foto da loja, descrição e contato.&lt;br&gt;
[RF05]: O sistema deve permitir que o lojista cadastre produtos&lt;br&gt;
[RF06]: O sistema deve permitir que o lojista possa alterar o preço do produto, quantidade e excluir produto.&lt;br&gt;
[RF08]: O sistema deve permitir que o lojista possa&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Cliente&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;[RF01]: O sistema deve permitir que o cliente se registrem sendo do tipo pessoa física ou jurídica.&lt;br&gt;
[RF02]: O sistema deve permitir que o cliente cadastre endereços, cartões para pagamentos e informações básicas de contato como email e telefone.&lt;br&gt;
[RF03]: O sistema deve permitir que o cliente adicione ao carrinho o item desejado&lt;br&gt;
[RF04]: O sistema deve permitir o pagamento de cartão de crédito ou pix&lt;br&gt;
[RF05]: O sistema deve permitir que o cliente escolha se prefere retirar na loja ou entrega(via transportadora).&lt;br&gt;
[RF06]: O sistema deve permitir que o cliente acompanhe o status do pedido, como: pedido feito, pedido autorizado, pedido em transporte e pedido entregue&lt;br&gt;
[RF07]: O sistema deve permitir que o cliente receba um email informando os itens comprados&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Comunidades&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;[RF01]: O sistema deve permitir que o um líder de comunidade se registre com informações do tipo quem são os líderes da comunidade CPF, CNPJ, informações de contato e endereço.&lt;br&gt;
[RF02]: O sistema deve permitir que o líder da comunidade liste todos os lojistas vinculada a essa comunidade.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Administrador&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;[RF01]: O sistema deve permitir o administrador listar todos os clientes cadastrados.&lt;br&gt;
[RF02]: O sistema deve permitir que o administrador liste todos os lojistas e consiga desautorizar o lojista que não esteja em conformidades com a regras da plataforma.&lt;br&gt;
[RF03]: O sistema deve permitir que o administrador liste todas as comunidades, tenha informações sobre os responsáveis delas e possa autorizar ou desautorizar as comunidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requisitos não funcionais(RNF)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Segurança&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;[RNF01]: O armazenamento dos tokens de acesso e de renovação deve ser seguro, preferencialmente em armazenamento seguro do navegador (por exemplo, localStorage ou cookies com flags Secure e HttpOnly).&lt;/p&gt;

&lt;p&gt;[RNF02]: O sistema deve implementar a renovação de tokens (refresh tokens) de forma segura para permitir sessões prolongadas sem comprometer a segurança.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NextJS/ReactJS&lt;/li&gt;
&lt;li&gt;NodeJS&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;minIO&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  System Design
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f1cmtw3fo67554tfv9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f1cmtw3fo67554tfv9w.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicando o Fluxo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;public-gateway&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; Atua como ponto de entrada para gerenciar e rotear. Redireciona o tráfego de entrada e saída entre a rede interna e externa.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;auth&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de Autenticação recebe as requisições de autenticação do &lt;strong&gt;public-gateway&lt;/strong&gt;, valida essas requisições, e faz chamadas apropriadas para o serviço de &lt;strong&gt;identity&lt;/strong&gt; para verificar as credenciais e gerenciar o registro dos usuários.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;identity&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de Identity gerencia as operações relacionadas aos usuários e contas, incluindo autenticação, registro, atualização de perfis.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;community&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de Community gerencia a criação, atualização e manutenção de dados de comunidades e seus respectivos responsáveis, incluindo endereços, e-mails e telefones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;customer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de Customer gerencia a criação, atualização e manutenção de dados de comunidades e seus respectivos responsáveis, incluindo endereços, e-mails e telefones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;marketplace&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de marketplace é responsável por gerenciar as operações essenciais de um marketplace, incluindo carrinho de compras, categorias de produtos, inventário e pedidos. Ele utiliza diversos modelos, como &lt;em&gt;Cart&lt;/em&gt;, que representa um carrinho de compras; &lt;em&gt;CartSessionCartItem&lt;/em&gt;, que gerencia a associação entre uma sessão de carrinho e itens; Category, que classifica os itens em categorias; e Department, que organiza os produtos por departamentos. Além disso, inclui Item, que representa os produtos disponíveis; &lt;em&gt;ItemMedia&lt;/em&gt;, para gerenciar as fotos dos itens; &lt;em&gt;ItemNumbering&lt;/em&gt;, que lida com a numeração dos itens; e &lt;em&gt;ItemSize&lt;/em&gt;, que define os tamanhos dos itens (P, M, G, etc.). O serviço também abrange &lt;em&gt;OrderItem&lt;/em&gt;, que representa itens dentro de um pedido; &lt;em&gt;OrderStatus&lt;/em&gt;, que gerencia o status dos pedidos; &lt;em&gt;OrderShipping&lt;/em&gt;, que lida com as informações de envio dos pedidos; e &lt;em&gt;OrderItemShipping&lt;/em&gt;, que gerencia o envio de itens específicos dentro de um pedido. Outros modelos incluem &lt;em&gt;ShippingToken&lt;/em&gt;, que representa tokens de envio para rastreamento; &lt;em&gt;ShippingService&lt;/em&gt;, que gerencia os serviços de envio disponíveis; e &lt;em&gt;StoreStoreAddress&lt;/em&gt;, que representa o endereço das lojas. O serviço permite a adição e remoção de itens do carrinho, a categorização e organização dos produtos, e o processamento completo dos pedidos, desde a criação até o envio.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;media&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript, minIO&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de media é responsável pelo gerenciamento e armazenamento de arquivos de mídia, incluindo fotos das lojas, fotos de perfil e fotos dos itens (produtos). Organiza por buckets do MinIO para armazenar essas mídias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;supplier&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de supplier gerencia a criação, atualização e manutenção de dados do lojista incluindo endereços, e-mails e telefones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;marketplace-cart-session-cron&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço de marketplace-cart-session-cron é responsável por gerenciar e limpar carrinhos de compras abandonados. Este serviço executa uma tarefa programada que verifica e remove carrinhos inativos no banco de dados. Para carrinhos de usuários não autenticados, ou seja, aqueles que não fizeram login, o serviço mantém o carrinho ativo por um período de 24 horas antes de removê-lo. Para carrinhos de usuários autenticados, o carrinho permanece ativo por 7 dias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;marketplace-order-cron&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; A crontab marketplace-order-cron é responsável pela automação do processo de verificação e atualização dos pedidos com status de pagamento pendente. O serviço opera em intervalos regulares para consultar todos os pedidos que estão com o status "pendente de pagamento". Para cada pedido identificado, o serviço realiza uma solicitação à API de pagamento para processar o pagamento. Se o pagamento for bem-sucedido, o serviço atualiza o status do pedido no banco de dados para refletir a nova condição.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;shipping-cron&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O Serviço shipping-cron é responsável por manter a validade dos tokens da API da transportadora. Este serviço é executado periodicamente para atualizar o token de autenticação, que é necessário para realizar chamadas à API da transportadora. Como os tokens fornecidos pela transportadora têm um período de expiração, o shipping-cron garante que um novo token seja obtido e registrado antes que o token atual expire, assegurando que as operações de envio e rastreamento continuem a funcionar sem interrupções.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;customer-external-consumer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; &lt;br&gt;
O customer-external-consumer é um serviço que consome mensagens de uma fila no RabbitMQ. Sua principal função é cadastrar clientes na API de pagamento e obter o identificador exclusivo do cliente fornecido pela API de pagamento. Esse identificador é então armazenado no banco de dados. Isso permite que, ao fazer pedidos de itens, o serviço envie à API de pagamento o identificador do cliente, facilitando a associação dos pagamentos com os clientes corretos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;supplier-external-consumer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O supplier-external-consumer é um serviço que consome mensagens de uma fila no RabbitMQ. Sua principal função é cadastrar (lojistas) fornecedores na API de pagamento e obter o identificador exclusivo do fornecedor fornecido pela API de pagamento. Esse identificador é então armazenado no banco de dados local. Isso permite que, ao processar transações relacionadas aos fornecedores, o serviço envie à API de pagamento o identificador do fornecedor, garantindo a correta associação dos pagamentos com os fornecedores registrados.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;email-consumer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tecnologia:&lt;/em&gt; NodeJS, Typescript&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Descrição:&lt;/em&gt; O email-consumer é um serviço que consome mensagens de email de uma fila no RabbitMQ. Ao receber uma mensagem, o serviço monta o template de email utilizando os atributos fornecidos no payload da mensagem. Após a montagem do email, o serviço envia o email formatado para o servidor SMTP para ser entregue ao destinatário.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dificuldades enfrentadas
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inicialmente, eu não quis trabalhar com nenhum ORM, o que foi um grande erro, porque no início, quando eu desenvolvia uma feature e o cliente pedia para adicionar ou remover uma nova informação, a manutenção das queries ficava bastante custosa. Então, tive que refatorar e adotei o ORM, facilitando a manutenção do sistema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inicialmente, não tínhamos um(a) designer para o projeto, então precisei dedicar muito tempo à construção dos layouts das telas, e o cliente acabou achando-os muito simples. No final do projeto, uma UX/UI foi integrada à equipe e conseguiu criar, no Figma, os layouts da maneira que o cliente desejava. Minha observação: ter um(a) UX/UI facilitará e agregará valor ao seu projeto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Como as especificações não estavam definidas desde o primeiro dia, a primeira versão foi desenvolvida de forma iterativa e contínua. Decidi aplicar os conceitos de Domain-Driven Design (DDD), mas, ao precisar refatorar, era necessário modificar muitos arquivos, como interfaces de repositório e validações. Então, para a versão 1 e considerando que o cliente ainda não tinha clareza sobre o que precisava ser implementado, eu optaria por uma arquitetura mais simples para facilitar o desenvolvimento. Acredito que isso tenha sido um exemplo de overengineering no projeto, o que custou tempo de desenvolvimento.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Melhorias futuras
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Adicionar um BFF (Backend For Frontend) com GraphQL, isso vai agregar bastante ao front-end ao consumir os dados da API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adicionar testes, já que temos vários serviços e, ao alterar um, é necessário que todos estejam consistentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adicionar CI/CD para automatizar a integração e deploy conforme as equipes forem contratadas para gerenciar o projeto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adicionar observabilidade dos serviços. [OpenTelemetry, Grafana]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adicionar CDN para imagens dos produtos.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Referência
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://engsoftmoderna.info/cap3.html" rel="noopener noreferrer"&gt;https://engsoftmoderna.info/cap3.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>engenhariadesoftware</category>
      <category>softwareengineering</category>
      <category>product</category>
      <category>saas</category>
    </item>
    <item>
      <title>Producer/Consumer (Produtor/Consumidor)</title>
      <dc:creator>Celso Costa</dc:creator>
      <pubDate>Tue, 23 Jul 2024 15:28:06 +0000</pubDate>
      <link>https://dev.to/jccl/producerconsumer-produtorconsumidor-1jok</link>
      <guid>https://dev.to/jccl/producerconsumer-produtorconsumidor-1jok</guid>
      <description>&lt;h2&gt;
  
  
  Definição
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Consideramos dois processos, chamados de “produtor” e “consumidor”, respectivamente. O produtor é um processo cíclico e cada vez que passa pelo seu ciclo produz uma determinada porção de informação, que deve ser processada pelo consumidor. O consumidor também é um processo cíclico e cada vez que passa pelo seu ciclo pode processar a próxima porção de informação, tal como foi produzida pelo produtor. Um exemplo simples é dado por um processo computacional, que produz como “porções de informação” imagens de cartões perfurados a serem perfurados por um cartão perfurado, que desempenha o papel do consumidor.[1]&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdayimui4rbceibqmj7t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdayimui4rbceibqmj7t8.png" alt="Image description" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicação
&lt;/h2&gt;

&lt;p&gt;Um produtor cria itens e os armazena em uma estrutura de dados, enquanto um consumidor remove os itens dessa estrutura e os processa.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se o consumo for &lt;strong&gt;maior que&lt;/strong&gt; a produção o buffer(estrutura de dados) esvazia, e o consumidor não tem o que consumir&lt;br&gt;
Se o consumo for &lt;strong&gt;menor que&lt;/strong&gt; a produção o buffer enche, e o produtor não consegue adicionar mais itens. Esse é um problema clássico chamado de &lt;strong&gt;buffer limitado&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Contextualização do Problema
&lt;/h2&gt;

&lt;p&gt;Suponha que temos um produtor que publica um e-mail no buffer, e um consumidor que consome o e-mail do buffer e exibe uma mensagem informando que foi enviado um e-mail com a nova senha de acesso para o e-mail informado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação em go
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;    &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;// fmt.Println("Foi adicionado o item " + item)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O Buffer não pode armazenar nenhum item mais está com a capacidade máxima"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"@email.com"&lt;/span&gt;
        &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Adiciona um pequeno atraso para simular produção&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enviado um email com a nova senha de acesso para: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explicando a implementação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Primeiro, criamos uma estrutura chamada &lt;em&gt;buffer&lt;/em&gt;, que contém um array de strings chamado &lt;em&gt;items&lt;/em&gt; e um mecanismo de controle do tipo mutex, chamado mu, para gerenciar o acesso concorrente.&lt;/li&gt;
&lt;li&gt;Temos duas funções: uma chamada add, que basicamente adiciona um item ao buffer, desde que haja espaço disponível, já que a capacidade do buffer é de apenas 5 itens; e outra chamada get, que, se houver itens no buffer, retorna o primeiro elemento e remove esse elemento do buffer.&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;Producer&lt;/em&gt; basicamente pega o index do loop e o concatena em uma string chamada &lt;em&gt;str&lt;/em&gt;, que contém o índice e um domínio de e-mail fictício, e adiciona no buffer. Foi adicionado um intervalo de tempo para simular um atraso.&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;Consumer&lt;/em&gt; solicita ao buffer um item, caso tenha ao menos um item. Em seguida, o Consumer exibe uma mensagem na tela informando que foi enviado um e-mail com a nova senha de acesso para o item que foi publicado publicado no buffer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link do código:&lt;/strong&gt; &lt;a href="https://github.com/jcelsocosta/race_condition/blob/main/producerconsumer/buffer/producerconsumer.go" rel="noopener noreferrer"&gt;https://github.com/jcelsocosta/race_condition/blob/main/producerconsumer/buffer/producerconsumer.go&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referência
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.cs.utexas.edu/%7EEWD/transcriptions/EWD01xx/EWD123.html#4.1.%20Typical%20Uses%20of%20the%20General%20Semaphore" rel="noopener noreferrer"&gt;https://www.cs.utexas.edu/~EWD/transcriptions/EWD01xx/EWD123.html#4.1.%20Typical%20Uses%20of%20the%20General%20Semaphore&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bibliografia
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.cin.ufpe.br/%7Ecagf/if677/2015-2/slides/08_Concorrencia%20(Jorge).pdf" rel="noopener noreferrer"&gt;https://www.cin.ufpe.br/~cagf/if677/2015-2/slides/08_Concorrencia%20(Jorge).pdf&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>producerconsumer</category>
      <category>monitor</category>
      <category>concurrency</category>
    </item>
    <item>
      <title>Race Condition (Condição de Corrida)</title>
      <dc:creator>Celso Costa</dc:creator>
      <pubDate>Mon, 22 Jul 2024 22:47:11 +0000</pubDate>
      <link>https://dev.to/jccl/race-condition-condicao-de-corrida-2461</link>
      <guid>https://dev.to/jccl/race-condition-condicao-de-corrida-2461</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Quando dois ou mais Threads/Processos competem por um recurso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Race Condition (Condição de Corrida)
&lt;/h2&gt;

&lt;p&gt;Iremos utilizar goroutines que é a forma de executar uma atividade de maneira concorrente em go.&lt;/p&gt;

&lt;p&gt;Problema:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Suponha que temos três clientes: um chamado A, outro chamado B e outro C. Todos estão interessados em comprar a mesma camisa em um e-commerce, porém existem apenas 10 unidades disponíveis dessa camisa. Crie uma goroutine para cada cliente e simule a compra dessa camisa, "printando" na tela qual cliente comprou a camisa, a quantidade comprada e qual a quantidade restante de camisas no estoque.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;itemType&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;itemId&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;unit&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;takeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Simula um atraso para aumentar a chance de condição de corrida&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O Cliente "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" comprou "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" unidade(s) de "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" e a quantidade restante no estoque é "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O Cliente "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" não conseguiu comprar "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" unidade(s) de "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;shirt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;441&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"camisa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerC&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw40wi93chcptvzt94ca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw40wi93chcptvzt94ca.png" alt="Image description" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dado que a camisa tem apenas 10 unidades e três clientes querem comprar um total de 12 unidades. A primeira resposta é que o Cliente C comprou 3 unidades de camisa e a quantidade restante no estoque é de 2 unidades. Porém, se o total de camisas é 10 unidades e o Cliente C comprou 3 unidades, deveria haver 7 unidades no estoque. Após o Cliente C, temos o Cliente A que não conseguiu comprar 4 camisas e, por fim, o Cliente B que conseguiu comprar 5 unidades, mostrando na tela que ainda há 5 unidades em estoque. Isso demonstra um problema de race condition onde temos threads/processos competindo por um recurso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adicionando o controle de concorrência com mutex
&lt;/h2&gt;

&lt;p&gt;Agora queremos que cada cliente que estiver com o item possa subtrair uma unidade desse item sem que nenhuma outra goroutine esteja acessando e modificando a quantidade do item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;itemType&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;itemId&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;unit&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;takeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Simula um atraso para aumentar a chance de condição de corrida&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O Cliente "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" comprou "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" unidade(s) de "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" e a quantidade restante no estoque é "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O Cliente "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" não conseguiu comprar "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" unidade(s) de "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;shirt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;441&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"camisa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;customerC&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customerC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;routineCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shirt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;itemType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;shirt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2tkgswvzm3mjey9pm8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2tkgswvzm3mjey9pm8f.png" alt="Image description" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora temos como saída o Cliente B comprando 5 unidades e a quantidade do estoque sendo 5, logo após o Cliente C comprando 3 unidades e a quantidade do estoque sendo 2, e por fim, o Cliente A não consegue comprar 4 unidades porque só existem 2 unidades disponíveis.&lt;/p&gt;

&lt;p&gt;Nesse caso, o que ocorre é o seguinte: quando uma goroutine tenta subtrair a unidade do item, ela deve chamar o método Lock do mutex para adquirir uma trava exclusiva. Se outra goroutine tiver adquirido a trava, essa operação ficará bloqueada até a outra goroutine chamar Unlock e a trava tornar-se disponível novamente. O mutex protege as variáveis compartilhadas.&lt;/p&gt;

&lt;p&gt;A região de código entre Lock e Unlock, em que a goroutine é livre para ler e modificar as variáveis compartilhadas, é chamada de seção crítica.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link do Código&lt;/strong&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/jcelsocosta/race_condition/tree/main" rel="noopener noreferrer"&gt;https://github.com/jcelsocosta/race_condition/tree/main&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referências&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DONOVAN, Alan A. A.; KERNIGHAN, Brian W. A Linguagem de Programação Go. 1. ed. São Paulo: Novatec, 2016. 400 p.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>race</category>
      <category>condition</category>
    </item>
  </channel>
</rss>
