Prévia do material em texto
explique para um leigo Computação pervasiva, transações e concorrência Há mais de 20 anos atrás, nos anos de 1990, a internet era discada. Isso significava que, para ter acesso à rede mundial de computadores, era necessário possuir uma linha telefônica, um provedor de acesso e um discador conforme ilustra a figura 1. Naquela época, para se conectar à internet era preciso abrir o discador, digitar o usuário e senha do provedor de acesso e ter certeza que ninguém utilizava a linha telefônica, afinal, se você se conectasse na internet, você estava, na realidade, realizando uma espécie de chamada telefônica e, deste modo, a linha ficava ocupada (tanto para fazer quanto para receber chamadas). Figura 1: Discadores privados de acesso à internet Ilustração colorida de 4 exemplos discadores privados de acesso à internet. Temos no canto superior esquerdo temos uma interface de formato arredondada, com informações sobre o uso, abaixo temos campos para inserir informações como nome, sobrenome, e-mail e CPF, contém um botão com a palavra concluir e abaixo temos o logo IG na parte inferior a direita. No canto superior direito temos uma interface com um formato ovais, ao lado esquerdo temos campo para inserir as informações pessoais e abaixo alguma informações, ao lado direito, temos o logo OI. Já no canto inferior esquerdo temos uma interface de forma arredondada e que no topo está o logo que é Telefônica, abaixo alguns campos como usuário, senha e opção para lembrar o acesso, ainda mais embaixo tem algumas informações como links de esqueci minha senha e mais abaixo o botão acessar. No canto inferior direito, temos uma interface de forma circular, no topo temos o logo IBEST, juntamente com um endereço web "https://www.google.com/search?q=.ibest.com.br", abaixo temos diversos campos para inserir informações, incluindo como login, senha, e-mail, nome completo, data de Nascimento, sexo, estado" e cidade, abaixo temos a vários informações. Fonte: https://imagens1.ne10.uol.com.br/blogsne10/mundobit/uploads/2013/05/discadores.jpg Eventualmente, se alguém tentasse ligar no número de telefone cuja linha estava sendo utilizada para você se conectar à internet, a sua conexão caía. Além disso, cada frequência de tempo que você ficava conectado era contada como um pulso de chamada telefônica, cada pulso era cobrado em unidades de centavos porém, ao final do mês, dependendo do tempo da conexão à internet, a conta telefônica poderia vir acima das centenas ou milhares de reais (sem exagero!). Nos anos de 1990 e um pouco do início dos anos 2000, “entrar na internet” (como era dito naquela época, porém o termo correto é conectar-se à internet) era realmente um evento. Você dizia: entrarei na internet para acessar o meu e-mail, entrarei na internet para ver uma notícia. Seria um tanto quanto estranho, para aquela época, ouvir alguém dizer: vou ligar o computador para ver notícias ou ver meus e-mails, afinal, o computador não tinha este recurso. Observe então que o ato de entrar ou conectar-se à internet não era algo transparente. Era necessária uma sequência de ações que, se bem-sucedidas, você teria acesso, se malsucedidas, você não se conectaria. Além disso, mesmo quando bem-sucedida, se alguém retirasse o telefone da base, ouviria um ruído estranho, afinal, pela linha telefônica estavam trafegando dados. Logo, não era nada transparente esta conexão com a internet. Vamos agora analisar nosso cenário atual: você liga o computador e pode acessar à internet, ler a notícia, pode checar seus e-mails, pode abrir suas redes sociais, interagir com aplicações, entre outras ações. Tudo isso apenas ligando o computador. E a internet? Hoje ela se tornou pervasiva ou ubíqua. Você só sente a internet quando ela falta (ou quando não sabe a senha de wi-fi do lugar onde está). Fora isso, você liga seu computador e, automaticamente, já está conectado a milhares de computadores e servidores no mundo todo. A internet então está aí, a sua disposição, você não precisa (literalmente) ir atrás dela, despender seu tempo para se conectar a um servidor. Também não mantém a linha telefônica ocupada. Diferentemente do final dos anos de 1990, você não precisa ficar receoso se seu download será interrompido pela queda da sua conexão (o que era muito comum naquela época devido a instabilidades). Este é o conceito de computação pervasiva ou ubíqua, é a onipresença da computação em nossas vidas, algo totalmente inimaginável na década de 1990. Agora, imagine no início dos anos de 1990, momento em que a internet começava a engatinhar e estávamos a anos luz do que temos hoje em relação à tecnologia, e o então professor do MIT Mark Weiser dizia em seu artigo intitulado The Computer for the 21st Century: “As tecnologias mais profundas são as que desaparecem. Elas se entrelaçam na trama da vida cotidiana, até se distinguirem dela” (WEISER, 1991). O que Weiser estava propondo era o conceito de computação pervasiva. A computação pervasiva, também chamada de computação ubíqua, é a tendência crescente de incorporar capacidade computacional (geralmente na forma de microprocessadores) em objetos do dia a dia para fazê- los comunicar-se com eficácia e realizar tarefas úteis de forma a minimizar a necessidade do usuário final de interagir com os computadores. Os dispositivos de computação difundidos são conectados à rede e estão constantemente disponíveis. Saiba Mais Veja o interessante artigo The Computer for the 21st Century publicado por Weiser na Scientific American Ubicomp em 1992 acessando o link https://www.ics.uci.edu/~corps/phaseii/Weiser-Computer21stCentury- SciAm.pdf E o link https://docplayer.com.br/655677-O-que-e-computacao-ubiqua.html Em outras palavras, é podermos ser avisados pelo smartwatch que está na hora de beber água, ou então, receber a informação no celular de que há alguém nos ligando via aplicativo de comunicação como whatsapp. Você não precisa se preocupar o tempo todo se seu smartphone, tablet, smartwatch ou qualquer dispositivo está ou não conectado à internet. Eles se conectam pois você previamente já fez isso no passado e, salvo algum ajuste ou problema técnico, ele só se desconectará da internet se você assim permitir. Deste modo, vivemos a computação pervasiva em todos os sentidos, afinal, a computação ubíqua ocorre com qualquer dispositivo, a qualquer momento, em qualquer lugar e em qualquer formato de dados, independentemente do tipo de rede, de modo a aceitar qualquer tipo de dispositivo, seja ele um laptop, um smartphone, um wearable, um smartwatch, um sensor entre outros. Por exemplo, você pode possuir um smartwatch que o alerte sobre uma chamada telefônica, a qual pode ser atendida em seu relógio; ou então, um sensor que afere a temperatura de um frigorífico e, quando a temperatura está fora do intervalo aceitável, emite uma mensagem de texto ou e-mail para os encarregados informando o evento. Computação pervasiva e internet das coisas A partir do conceito de computação pervasiva surgiu então o conceito de Internet das Coisas ou IoT. Como na computação pervasiva, em IoT os dispositivos se conectam à internet para se comunicar trocando mensagens. Observe que a onipresença da internet discutida anteriormente, possibilitou que dispositivos (chamado de coisas) possam se comunicar e, consequentemente, toda esta comunicação entre as coisas passa desapercebida, de maneira transparente, para nós usuários. A visão da computação pervasiva corresponde a colocar poder computacional em objetos do dia a dia. IoT está a caminho de fornecer essa visão e transformar objetos comuns em dispositivos conectados, mas, a partir de agora, requer uma grande quantidade de configuração e interação humano-computador algo que a computação ubíqua de (Weiser, 1991) não exigia. Esta é uma explicação muito breve sobre IoT, que é capaz de empregar redes de sensores sem fio (RSSF) para coletar dados de sensores individuais e retransmiti-los para o servidor IoT em nuvem. SaibaMais Falamos aqui sobre internet das coisas ou IoT. Conheça mais sobre este conceito que está em ascensão, com diversas aplicações com as quais interagimos no dia a dia, durante a leitura do artigo Desvelando a Internet das Coisas, em que o autor percorre um caminho que se inicia a partir da discussão da máquina de Turing e culmina na internet em seu estado atual. Acesse o artigo em: https://www.researchgate.net/profile/Adelino- Gala/publication/327601891_Desvelando_a_Internet_das_Coisas Estudo de casos Vamos analisar o caso de uma determinada empresa que estava preocupada com o alto valor da conta de água, a qual teve um aumento substancial nos últimos dois meses. A ação da empresa foi colocar alguns sensores em algumas áreas consideradas sensíveis: entrada de água da rua para a caixa d’água, saída da caixa d’água para abastecimento interno, sensores em todas as saídas internas como em banheiros e cozinhas (lugares onde existam torneiras e outras fontes de saída de água). Após feita a instalação dos sensores e do sistema completo, a empresa começou a monitorar a quantidade de água que entrava da rua para a caixa e o percurso desta água em toda rede interna. Logo, se entrassem por exemplo, 1000 litros de água, haveria necessidade de sair os mesmos 1000 litros. A empresa então observou que em um dos sensores estava apresentando uma medida inconsistente. No caminho deste sensor (vamos chamá-lo de X), estava entrando um volume de água, porém o que estava saindo pelas torneiras era duas vezes menor. Deste modo, por aquele caminho do sensor X havia um vazamento. A empresa então pôde resolver o problema. Existem outros exemplos de computação pervasiva, por exemplo, a automação nos pedágios. Você pode adquirir uma etiqueta que, ao passar pelo sistema eletrônico do pedágio, a cancela abre automaticamente para você. Isso é computação pervasiva e este é um exemplo de aplicação de IoT. Você não precisa se preocupar em ter que pegar seu dinheiro, entregar para o caixa no pedágio, aguardar o troco e a liberação (assim como era a internet dos anos de 1990, em que você abria o discador, aguardava a conectividade e só assim tinha acesso à internet), tudo é automático, tudo é pervasivo. Outra aplicação para IoT é aplicar o uso de sensores no campo. Um agricultor, que cultiva café precisa analisar diariamente algumas informações do solo e também da plantação. Do solo, precisa tirar informações como nível de PH, umidade, salinidade, entre outras informações. Das plantas, é necessário obter o nível de umidade e se existe alguma doença instalada. Considerando que este agricultor possui cerca de 1000 pés de café, fica inviável percorrer diariamente esta plantação para coletar todas estas informações. Além disso, após analisar a amostra 990, certamente a primeira amostra pode ter sofrido alguma modificação, logo, o dado inicial já não é mais válido. Portanto, parece difícil verificar cada pé de café e o solo em sua volta. Desse modo, é aí que os dispositivos IoT podem ser utilizados, sendo potencializados com o aprendizado de máquina. Ao extrair dados de vários sensores no solo e nas plantas, os algoritmos de aprendizado de máquina podem aprender o que é típico do solo e da planta e, então, detectar se algo anormal começa a ocorrer. Assim, eles podem aprender e prever riscos futuros e convertê-los em dados acionáveis. Desse modo, observe nestes casos como a computação pervasiva faz a diferença e realiza um forte impacto nas vidas de todos nós, seja na cidade, no campo ou na indústria. O ChatGPT disse: Beleza 👍 vou te explicar de forma simples, como se fosse uma conversa do dia a dia. 1. Computação pervasiva (ou ubíqua) Pensa assim: nos anos 90 você precisava de todo um ritual para “entrar na internet” — abrir o discador, esperar a conexão, não podia usar o telefone ao mesmo tempo… Hoje em dia você nem percebe, a internet já está aí: no celular, no relógio, na TV, no carro, até na geladeira. 👉 Isso é computação pervasiva: a tecnologia está “espalhada por todo lugar”, funcionando de fundo sem você precisar pensar nela. Você só percebe quando falta. 2. Transações Agora, imagina que você vai ao mercado e passa as compras no caixa. Você paga, o sistema precisa descontar do estoque, registrar a compra, atualizar o limite do seu cartão etc. Tudo isso acontece em sequência e tem que dar certo de ponta a ponta — se a luz cair no meio, não pode descontar seu dinheiro sem registrar sua compra, por exemplo. 👉 Isso é uma transação em sistemas: um conjunto de operações que só vale se todas forem concluídas corretamente. Ou tudo acontece, ou nada acontece. 3. Concorrência Já a concorrência é como quando várias pessoas tentam usar o caixa do mercado ao mesmo tempo. Nos sistemas, acontece quando vários usuários ou programas querem acessar os mesmos dados simultaneamente. Por exemplo: você e outra pessoa transferem dinheiro da mesma conta ao mesmo tempo. O sistema precisa organizar quem faz o quê primeiro para não dar confusão no saldo. 👉 Concorrência é essa “coordenação” para que todos possam usar os recursos sem bagunça ou erro. Resumindo com exemplos práticos: Computação pervasiva → seu relógio avisa que você tem consulta, o carro mostra o melhor caminho, e tudo isso sem você pedir. Transações → comprar algo no cartão: só é válido se tudo for registrado corretamente (compra + débito + nota). Concorrência → várias pessoas usando o mesmo aplicativo de banco ao mesmo tempo, sem que o sistema perca o controle das contas. Quer que eu monte isso em um mapinha mental bem visual, mostrando como esses três conceitos se relacionam no dia a dia? Você disse: explique para um leigo Transação distribuída As transações foram originadas a partir dos sistemas de gerenciamento de banco de dados (SGBDs), sendo que uma transação distribuída refere-se a um conjunto de operações em dados que são executadas em dois ou mais repositórios de dados (especialmente bancos de dados). Normalmente, estas transações são coordenadas entre nós separados conectados por uma rede, mas também pode abranger vários bancos de dados em um único servidor. Em um processo de transação distribuída podemos obter dois resultados: 1) Todas as operações são concluídas com êxito; 2) nenhuma das operações é realizada devido a uma falha em alguma parte do sistema. Neste último caso, se algum trabalho foi concluído antes da falha, esse trabalho será revertido para garantir que nenhuma ação na rede tenha sido realizada. Esse tipo de operação está em conformidade com os princípios ACID (figura 2) de bancos de dados relacional que garantem a integridade dos dados: • Atomicidade: cada transação deve ser executada na integralidade, sendo totalmente bem-sucedida ou totalmente revertida; • Consistência: cada transação de alteração dos dados deve manter a integridade dos dados ou será cancelada completamente; • Isolamento: cada transação de leitura ou gravação realizada no banco de dados não será afetada por outra transação de leitura ou gravação que esteja ocorrendo simultaneamente no mesmo banco de dados; • Durabilidade: cada transação confirmada no seu banco de dados deve ser permanente, mesmo que o sistema possa sofrer alguma falha. Figura 2: Conceitos ACID Ilustração colorida dividida em duas colunas. Na coluna da esquerda temos 4 retângulos o primeiro com a letra a, abaixo temos a letra c, abaixo temos a letra i e abaixo a letra d. Na outra coluna temos 4 retângulos o primeiro temos a informação atomicidade, abaixo consistência, abaixo isolamento e por último durabilidade. Fonte: Elaborado pelo autor (2021) O conceito de ACID é mais comumente associado a transações em um único servidor de banco de dados, mas as transações distribuídas estendem essa garantia a vários bancos de dados. Observe com atenção o terceiro item do conceito ACID que é o Isolamento, o qual significa que uma transação que estiver em execução não pode sofrer interferência por nenhuma outra transação até que ela sejaconcluída (validada). O isolamento perfeito pode ser alcançado trivialmente por meio da execução serial: executando todas as transações no sistema, uma de cada vez, sem simultaneidade. Isso tem implicações terríveis de desempenho; felizmente, também não é necessário atingir o isolamento perfeito. Muitos bancos de dados simultâneos oferecem execução serializável que é equivalente à execução serial, permitindo um nível considerável de transações simultâneas. A serialização então é uma garantia sobre transações ou grupos de uma ou mais operações sobre um ou mais objetos. Ela garante que a execução de um conjunto de transações (geralmente contendo operações de leitura e gravação) sobre vários itens é equivalente a alguma execução serial (ordenação total) das transações. Se as transações dos usuários preservarem a consistência da aplicação (“C” ou consistência no ACID), uma execução serializável também preservará a consistência. Portanto, a serialização é um mecanismo para garantir a exatidão do banco de dados. Saiba Mais No artigo Desenvolvimento de um mecanismo de transações para sistemas distribuídos, os autores realizam o estudo e desenvolvimento de técnicas que permitam o gerenciamento de transações garantindo o funcionamento das propriedades ACID. Acesse o artigo em: http://www.inf.furb.br/seminco/2002/artigos/Borchardt-seminco2002-11.pdf O ChatGPT disse: Ótima pergunta 👌 vou te explicar como se você nunca tivesse ouvido falar de “transação distribuída”. 1. Primeiro, o que é uma transação simples? Pensa numa compra com cartão no mercado: você passa as compras no caixa, o sistema desconta o estoque, o banco aprova o pagamento, o caixa emite a nota. 👉 Tudo isso tem que dar certo junto. Se a luz cair no meio, a compra é cancelada por completo (nem desconta seu dinheiro, nem baixa o estoque). Isso é uma transação: ou tudo acontece, ou nada acontece. 2. E o que muda na transação distribuída? Agora imagina que sua compra envolve vários sistemas diferentes ao mesmo tempo: o banco que aprova o cartão está em São Paulo, o estoque do supermercado está em um servidor no Rio, o programa que gera a nota fiscal está em Brasília. Esses três lugares precisam conversar entre si e se coordenar para que a transação aconteça sem erros. 👉 Se qualquer um deles falhar, todos os outros desfazem o que já foi feito, como se nada tivesse acontecido. É isso que chamamos de transação distribuída: quando uma operação depende de vários bancos de dados ou servidores diferentes trabalhando juntos. 3. O papel do ACID (atomicidade, consistência, isolamento e durabilidade) Esses quatro princípios garantem que os dados fiquem sempre corretos, mesmo no meio da bagunça: Atomicidade → ou tudo acontece ou nada acontece. Consistência → os dados não podem ficar “quebrados” (ex.: saldo negativo indevido). Isolamento → sua transação não atrapalha a do outro, mesmo acontecendo ao mesmo tempo. Durabilidade → se deu certo, está gravado de vez (mesmo se o sistema cair depois). 4. Exemplo bem do dia a dia Você transfere dinheiro do seu banco para pagar uma passagem aérea online: O servidor do banco precisa descontar o valor da sua conta. O servidor da companhia aérea precisa reservar seu assento. O servidor da operadora de cartão precisa validar a cobrança. 👉 Isso tudo tem que ser coordenado como uma única transação distribuída: Se todos confirmarem, a compra é feita. Se algum falhar, tudo volta atrás: seu dinheiro não sai, a reserva não é feita, e a cobrança não é registrada. 💡 Em resumo: Uma transação distribuída é como um combinado entre vários sistemas diferentes para executar uma única operação. Ou todos fazem a parte deles com sucesso, ou todos cancelam, garantindo que não haja erros ou inconsistências. Quer que eu faça um passo a passo ilustrado (tipo uma historinha em quadrinhos) mostrando como essa transação distribuída acontece no exemplo da compra da passagem? Isso deixa ainda mais claro para leigos. Você disse: explique para um leigo da melhor forma Lost Update O problema chamado Lost Update ou atualização perdida ocorre quando duas transações simultâneas tentam ler e atualizar os mesmos dados. Veja o seguinte exemplo em que temos uma tabela chamada “produto” que armazena id, nome e ItensEmEstoque para um produto. Essa tabela é usada em um sistema para exibir o número de itens em estoque para um determinado produto e, portanto, precisa ser atualizada cada vez que uma venda desse produto é feita. Agora, considere as duas transações da figura 3, em que transação 1 é o cliente 1 e transação 2 é o cliente 2, ambos estão realizando a compra ao mesmo tempo no site. Figura 3: Exemplo de transações concorrentes Ilustração colorida de um diagrama dividido em 2 colunas. Na primeira coluna do lado esquerdo temos o retângulo transição 1 e abaixo temos o retângulo e duas linha abaixo temos o retângulo comprar 2 itens e mais abaixo o retângulo atualizar estoque. Ao lado temos uma seta para baixo na vertical separando as colunas. A coluna da direita temos o retângulo transição 2, mais abaixo o retângulo itens em estoque?, abaixo o retângulo comprar 3 itens e um pouco mais abaixo o retângulo atualizar estoque. Fonte: Elaborado pelo autor (2021) Observe pela figura 3 que o cliente 1 (transação 1) inicia o processo de compra do produto X. Ao mesmo tempo, em outro lugar, o cliente 2 (transação 2) inicia o processo de compra do mesmo produto X. A transação 1 lê os itens em estoque para o produto X que nesse caso é 12. Um pouco depois (talvez milésimos de segundos), a transação 2 lê o valor da variável de ItensEmEstoque para o produto X que ainda será 12 neste momento (afinal, ainda não foi atualizado o valor de estoque deste produto). Na transação 2 o cliente compra três produtos X, pouco antes da transação 1 comprar 2 produtos X. Qual o valor atual do estoque? A Transação 2 então completará sua execução primeiro e atualizará a variável ItensEmEstoque para 9, uma vez que o cliente comprou três dos 12 produtos X. A transação 1 finaliza. Como o cliente na transação 1 comprou dois itens, a variável ItensEmEstoque valerá 10. Temos então uma inconsistência! Bloqueios transacionais (locks transitions) Uma transação bloqueada é aquela que, além das ações de leitura e escrita como da figura 3, contém operações de bloqueio e desbloqueio para os itens de dados. Neste tipo de transação, as operações de bloqueio e desbloqueio permitem que um sistema controle a ordem das ações de leitura e escrita de um conjunto simultâneo de transações. Uma política de bloqueio possui um conjunto de regras que restringe as maneiras possíveis de introduzir operações de bloqueio e desbloqueio em uma transação. Uma política de bloqueio é segura se, sempre que todas as transações estiverem em conformidade com a política, qualquer histórico das transações será serializável. O bloqueio de duas fases que veremos a seguir é um exemplo de uma política de bloqueio segura que se baseia na regra simples que diz que uma transação não tem permissão para bloquear um item de dado, uma vez que já desbloqueou algum item de dado. Bloqueio de duas fases (two phase locking) Os bloqueios por si só não são suficientes para evitar conflitos. Uma estratégia de controle de simultaneidade deve definir como os bloqueios estão sendo adquiridos e liberados, pois isso também tem um impacto na intercalação da transação. Para este propósito, o protocolo bloqueio de duas fases, two phases locking ou simplesmente 2PL define uma estratégia de gerenciamento de bloqueio para garantir a serialização estrita. O protocolo 2PL divide uma transação em duas fases: • fase de expansão (bloqueios são adquiridos e nenhum bloqueio pode ser liberado); • fase de encolhimento (todos os bloqueios são liberados e nenhum outro bloqueio pode ser adquirido). Para uma transação de banco de dados, a fase de expansão significa que os bloqueios (locks) podem ser adquiridos desde o início da transação até o seu final, enquanto a fasede redução é representada pela fase de commit ou rollback, como no final de uma transação, todos os locks adquiridos serão liberados. O diagrama da figura 4 mostra como a intercalação de transação é coordenada por 2PL, para isso, utilizaremos o mesmo exemplo da figura 3. Figura 4: Exemplo de emprego do protocolo 2PL Ilustração colorida de um diagrama dividido em 2 colunas. Na primeira coluna do lado esquerdo temos o retângulo transição 1, abaixo temos fase de aquisição de bloqueio, abaixo itens em estoque, abaixo comprar 2 itens, abaixo atualizar estoque e por último fase de liberação de bloqueio. Ao lado temos uma seta apontando para baixo na vertical separando as colunas. Ao lado direito temos a segunda coluna, temos o retângulo transição 2, abaixo a fase de aquisição de bloqueio, abaixo itens em estoque, abaixo aguarda pelo bloqueio, abaixo comprar 2 itens, abaixo atualizar estoque abaixo a palavra com e abaixo o último retângulo fase de liberação de bloqueio. Fonte: Elaborado pelo autor (2021) Observe pela figura 4 que o cliente 1 e o cliente 2 adquirem o bloqueio de leitura em um determinado registro (no caso a variável ItensEmEstoque). Quando o cliente 2 tenta realizar uma compra de 3 itens, ou seja, tenta atualizar a variável ItensEmEstoque, sua instrução é bloqueada pelo lock manager. Isso ocorre, pois, para escrever na variável, a transação necessita bloquear a variável primeiramente, porém ela já está bloqueada pela transação do cliente 1. Somente após a transação do cliente 1 terminar e todos os bloqueios forem liberados, o cliente 2 poderá retomar a operação de atualizar a variável ItensEmEstoque. O ChatGPT disse: Boa! 👌 Vou explicar o Lost Update (atualização perdida) de um jeito bem simples, sem “tecniquês demais”. O que é o problema? Imagine que você e um amigo vão no mesmo site para comprar o último tênis em estoque. O sistema mostra para os dois que ainda existem 12 pares disponíveis. Você decide comprar 2 pares. Seu amigo decide comprar 3 pares. 👉 Como os dois fizeram isso quase ao mesmo tempo, cada um viu a informação “12 pares” no sistema. O que acontece depois? O sistema processa primeiro a compra do seu amigo → ele tira 3 pares → agora restariam 9 pares. Mas logo depois o sistema processa a sua compra → mas ele ainda acha que havia 12 pares (porque leu antes da atualização). Então ele subtrai 2 de 12 = 10 pares. 👉 No final, o estoque fica mostrando 10 pares, mas o correto seria 7 pares. Ou seja, uma atualização se perdeu → o sistema “esqueceu” que já tinha vendido 3 pares. Por que isso acontece? Porque duas operações tentaram ler e alterar a mesma informação ao mesmo tempo, e uma sobrescreveu o resultado da outra. É como duas pessoas anotando em uma lousa: A primeira escreve “12 - 3 = 9”. A segunda, que ainda viu “12”, escreve “12 - 2 = 10”. 👉 O resultado final não bate com a realidade. Como resolver? Para evitar essa bagunça, os sistemas usam bloqueios (locks): Quando alguém começa a atualizar o estoque, o sistema trava esse dado. A outra pessoa que tentou comprar ao mesmo tempo tem que esperar a primeira terminar. Assim, o estoque sempre é atualizado de forma correta e sequencial. Esse método de “esperar o outro terminar” é chamado de 2PL (two-phase locking). Resumindo: primeiro todo mundo pega o cadeado do dado que vai mexer, só depois libera. Resumo rápido para leigos Lost Update = quando duas pessoas mexem no mesmo dado ao mesmo tempo, e uma sobrescreve a alteração da outra. Exemplo = duas compras simultâneas do mesmo produto → o estoque final fica errado. Solução = o sistema usa “cadeados” (locks) para que apenas uma atualização seja feita por vez, garantindo que nada se perca. Quer que eu faça uma metáfora do dia a dia (fora do computador)? Tipo comparar isso com duas pessoas mexendo ao mesmo tempo numa lista de compras de papel, para deixar ainda mais fácil de visualizar? Você disse: explique isso O protocolo 2PL divide uma transação em duas fases: • fase de expansão (bloqueios são adquiridos e nenhum bloqueio pode ser liberado); • fase de encolhimento (todos os bloqueios são liberados e nenhum outro bloqueio pode ser adquirido). O ChatGPT disse: Beleza, vou explicar de forma simples. O protocolo 2PL (Two-Phase Locking) é usado em bancos de dados para garantir que as transações sejam feitas de forma segura (sem dar problema de inconsistência nos dados). Ele divide a vida de uma transação em duas fases: 🔒 1. Fase de Expansão (ou crescimento) Aqui, a transação só pode adquirir novos bloqueios (locks). Um bloqueio é como reservar um recurso, por exemplo: “ninguém mais pode mexer nessa linha da tabela até eu terminar”. Nesta fase, a transação vai pegando os bloqueios que precisa, mas não pode soltar nenhum ainda. 💡 É como ir ao mercado: você vai colocando itens no carrinho, mas ainda não pode devolver nada. 🔓 2. Fase de Encolhimento (ou liberação) Quando a transação libera o primeiro bloqueio, ela entra nessa fase. A partir daí, ela só pode liberar bloqueios, mas não pode adquirir nenhum novo. Ou seja: depois que começou a soltar, não pode mais pegar nada. 💡 Voltando ao mercado: é como chegar no caixa. Você só pode pagar e entregar os itens do carrinho, mas não pode mais sair para pegar outros produtos. 🚦 Por que isso é importante? Esse protocolo evita problemas de concorrência entre transações, como: Leituras sujas (ler um dado que ainda pode mudar); Perda de atualização (uma transação sobrescrevendo o trabalho da outra); Inconsistência no banco de dados. No fim, o 2PL garante que o resultado seja o mesmo que se as transações fossem executadas uma por vez, em sequência, mesmo que estejam rodando ao mesmo tempo. Quer que eu te mostre um exemplo prático em banco de dados (tipo duas pessoas transferindo dinheiro entre contas) para entender como esse protocolo funciona na prática? Você disse: explique para um leigo Deadlock Suponha que você está em uma estrada. À frente, você se depara com uma ponta onde é possível passar apenas um carro por vez. Ao acessar a ponte, um outro carro também acessa como na figura 5. Você espera que a pessoa à frente dê uma volta e forneça o caminho para você. Entretanto, a pessoa à sua frente está esperando que você permita que ela passe. Figura 5: Exemplo de deadlock Ilustração colorida no qual temos linhas paralelas na horizontal que se aproximam no centro da imagem formando uma seção mais estreita, e depois se afastam novamente. A via começa com duas faixas de tráfego em cada sentido no total de quatro faixas. No gargalo, a via se estreita para apenas uma faixa em cada sentido no total de duas faixas. Após o gargalo, a via volta a ter duas faixas em cada sentido. Uma linha tracejada central indica a divisão entre os sentidos do tráfego. No lado esquerdo antes do gargalo, há dois carros na faixa inferior indo para a direita e mais a frente no gargalo um carro sentido a direita. No lado direito após o gargalo, há dois carros na faixa superior indo para a esquerda e mais a frente no gargalo um carro indo para a esquerda. Fonte: Elaborado pelo autor (2021) A ponte, neste exemplo da figura 5, representa um recurso computacional. Esta é uma situação de impasse em que ambos estão presos e ninguém está pronto para voltar atrás. Em sistemas computacionais chamamos essa situação de deadlock. Deadlock representa uma condição indesejada em que dois ou mais processos aguardam indefinidamente que o outro processo libere seus recursos para que possam concluir seu trabalho (os três carros à esquerda aguardam que o carro à direita na ponte libere a passagem, porém o mesmo ocorre do outro lado). Considere agora uma situação em que existem dois processos que estão executando simultaneamente, chamaremos de P1 e P2. Observe a figura 6. Confira na figura 6 que o processo P1 está retendo o recurso R2 e necessita do recurso R1 para concluir sua execução. Por outro lado, o processo P2 retém o recurso R1 e precisa do recurso R2 para concluir sua execução.Logo, há uma situação em que um processo está aguardando o outro processo liberar seu recurso e, portanto, o processo não consegue concluir sua execução. Consequência: o sistema para. Um deadlock ocorre durante o bloqueio transacional (bloqueio de duas fases), quando uma transação T1 está esperando por um recurso que está bloqueado exclusivamente por outro recurso T2. Ao mesmo tempo, a transação T2 está retendo aquele recurso e está aguardando os recursos retidos pela transação T1. Figura 6: Exemplo de deadlock entre processos e recursos. Ilustração de um diagrama onde temos da esquerda para a direita um circulo que dentro contém a informação P1 acima na diagonal uma seta apontando para o quadrado R1 e sai uma seta para baixo na diagonal apontando para um círculo que contém a informação P2 que dele sai uma seta para baixo na diagonal para o lado esquerdo apontando para o quadrado R2 que sai uma seta na diagonal para a esquerda apontando para o círculo P1. Fonte: Elaborado pelo autor (2021) Para que haja o deadlock, as quatro condições a seguir devem ser mantidas simultaneamente: • Exclusão mútua: alguns recursos envolvidos não podem ser usados por mais de um processo ao mesmo tempo (um recurso pode ser mantido apenas por um processo). Isso significa que se o recurso (como uma impressora) estiver sendo usado por qualquer processo e algum outro processo vier, ele terá que aguardar a liberação dos recursos; • Sem preempção: se um processo está mantendo um recurso, então seus recursos não podem ser retirados à força dele; • Retenção e espera: o processo está retendo alguns recursos e aguardando outros recursos; • Espera circular: o processo está aguardando o recurso que está sendo retido pelo próximo processo e isso forma uma cadeia de espera. No exemplo acima, o Processo P1 e o Processo P2 estão formando uma cadeia e aguardando que o recurso seja mantido um pelo outro. A figura 7 ilustra a espera circular; Figura 7: Exemplo de espera circular Ilustração de um diagrama onde temos da esquerda para a direita um círculo com informações P1 acima na diagonal para a direita o círculo P2, e ao lado uma seta na diagonal para baixo lado direito para o círculo P3 e sai uma seta para baixo na diagonal sentido esquerdo apontando para o círculo no centro na parte de baixo P4 e sai uma seta na diagonal para cima para a esquerda para o círculo P1. Fonte: Elaborado pelo autor (2021) Observe pela figura 7 que todos os processos estão aguardando um determinado recurso de forma cíclica, em que o último processo (P4) aguarda o recurso retido pelo primeiro processo (P1), o qual aguarda o processo retido por (P2) e este aguarda o processo retido por (P3), formando um ciclo. Por fim, observe que se alguma das condições apresentadas anteriormente falhar, o sistema então ficará livre do deadlock (você verá que, quebrar este ciclo da figura 7, é uma das estratégias para nos livrarmos do deadlock). O ChatGPT disse: Ótima pergunta 👌. Vou te explicar deadlock como se fosse para um leigo, sem tanto “tecniquês”. 🚗 O exemplo da ponte Imagine uma ponte estreita em que só passa um carro por vez. Um carro vem da esquerda (quer atravessar para a direita). Outro carro vem da direita (quer atravessar para a esquerda). Os dois entram juntos na ponte e ficam cara a cara. O carro da esquerda espera que o da direita dê ré. O carro da direita espera que o da esquerda dê ré. Resultado: ninguém anda. Isso é o deadlock → uma situação de “empate” onde todos ficam travados esperando o outro liberar o caminho. 1. 2. 3. 4. 🖥 No computador No lugar dos carros, pense em programas (processos). No lugar da ponte, pense em um recurso do computador (ex.: impressora, banco de dados, memória). ➡ Se um processo segura um recurso e fica esperando outro que está sendo usado por outro processo (que, por sua vez, espera o primeiro liberar)… pronto: deadlock. 🔑 As quatro condições para existir deadlock Para que esse “engarrafamento” aconteça, quatro coisas precisam estar presentes ao mesmo tempo: Exclusão mútua: um recurso só pode ser usado por um processo de cada vez (como uma impressora que só imprime um arquivo por vez). Sem preempção: o recurso não pode ser tomado à força, tem que ser liberado “de boa vontade” pelo processo. Retenção e espera: o processo já está segurando um recurso e continua esperando por outro. Espera circular: forma-se uma “roda” de espera, onde cada processo está esperando algo que o outro não solta. Se essas quatro coisas acontecerem juntas, o sistema trava. 💡 Como evitar deadlock? Quebrar o ciclo: garantir que não exista espera circular. Liberar recursos cedo: não ficar segurando o que não está usando. Forçar ordem: definir regras para quem pega primeiro os recursos. Timeout: se esperar muito, desistir e tentar de novo. 👉 Resumindo: Deadlock é como um engarrafamento sem solução dentro do computador, onde dois ou mais programas ficam esperando recursos que nunca serão liberados porque estão “presos” uns aos outros. Quer que eu monte um mini exemplo com banco de dados (tipo duas transações que ficam esperando dados uma da outra) para você visualizar deadlock no mundo real da computação? Você disse: explique para um leigo Deadlock em sistemas distribuídos As mesmas condições para deadlock em ambiente com um processador se aplicam a sistemas distribuídos. Entretanto, o deadlock em sistemas distribuídos é mais difícil de detectar, evitar e prevenir. Quatro estratégias podem ser usadas para lidar com o deadlock: 3) Ignorar o deadlock: ignore o problema, suponha que nunca ocorrerá um deadlock, afinal, a ocorrência de um deadlock é rara, então, para que escrever um código para removê-lo? Se escrevermos um código para remover o deadlock, teremos a contrapartida de deixar o sistema mais lento, degradando-o. Sistemas operacionais como Windows e Linux utilizam este método da ignorância de deadlock: se o sistema parar, reinicie para prosseguir. 4) Prevenir o deadlock: devemos evitar que o deadlock aconteça, eliminando uma ou mais condições que provocam o deadlock: a) remover a exclusão mútua: os recursos devem ser compartilhados, de modo que dois ou mais processos possam usá-lo ao mesmo tempo; b) remover a preempção: um processo será forçado a parar (será interrompido) e, deste modo, os recursos que estão sendo retidos por este processo serão liberados; c) remover a retenção e espera: um processo receberá todos os recursos que são necessários antes que ele inicie. Desse modo, ele terá todos os recursos e não necessitará esperar. Trata-se de uma condição quase impossível, afinal, não podemos entregar todos os recursos para um processo. Pode ocorrer o chamado Starvation; d) remover a espera circular: podemos enumerar os recursos e cada processo poderá acessá-los em ordem crescente desta numeração. Observe que, se implementado esse algoritmo, haverá um aumento na complexidade do sistema e, consequentemente, levará a má utilização do recurso. 5) Evitar o deadlock: os recursos devem ser escolhidos com cuidado para que o deadlock não ocorra. Deste modo, é necessário prever os recursos que serão utilizados antes que o processo seja executado. 6) Detectar o deadlock: devemos permitir que o deadlock ocorra e, quando ocorrer, devemos detectá-lo, remover o deadlock e reiniciar o processo que o causou. Starvation O starvation ocorre quando um processo solicita um recurso e esse recurso foi continuamente usado por outros processos, então o processo solicitante enfrenta a inanição. No starvation, um processo pronto para execução espera que lhe seja atribuído um recurso; mas o processo tem que esperar indefinidamente, pois os outros processos bloqueiam continuamente os recursos solicitados. Esse tipo de problema geralmente ocorre no algoritmo de escalonamento de prioridade em que um recurso é sempre alocado para um processo com maior prioridade, evitando que o processo de menor prioridade obtenha o recurso solicitado. Quando removemos a retençãoe a espera para evitar o deadlock, podemos ter o estado de starvation, pois como os recursos foram alocados antecipadamente para um processo, os demais processos ficarão aguardando indefinidamente por um ou mais destes recursos. Uma solução para o starvation é o envelhecimento ou aging de um processo. O envelhecimento é responsável por aumentar gradativamente a prioridade do processo que está esperando há muito tempo pelos recursos. Desse modo, um processo que estava esperando por um recurso, envelhecerá e, em um dado momento, terá acesso ao recurso requisitado. Verifique então que tanto o deadlock quanto o starvation bloqueiam e atrasam a execução de processo. O quadro 1 a seguir apresenta um comparativo entre ambos. Tabela 1: Comparativo entre deadlock e starvation Deadlock Starvation Todos os processos são bloqueados e nenhum deles continuam a execução. Processos de baixa prioridade são bloqueados e processos de alta prioridade continuam a execução Os recursos solicitados são bloqueados por outros processos Os recursos solicitados são usados por processos de alta prioridade Podemos prevenir evitando a exclusão mútua, removendo a retenção e espera, permitindo a preempção e remover a espera circular. Podemos prevenir utilizando o envelhecimento de processos. Fonte: Elaborado pelo autor (2021) Por fim, observe que o deadlock pode fazer com que os processos fiquem em starvation, porém, por outro lado, o starvation pode tirar os processos do deadlock. 1. 2. 3. 4. O ChatGPT disse: Boa! Vamos traduzir isso para o mundo real, sem complicação. 🚦 Deadlock em sistemas distribuídos Lembra do engarrafamento da ponte que te expliquei antes? Agora imagine que, em vez de uma única ponte, temos várias pontes espalhadas em diferentes cidades (que seriam os computadores da rede). ➡ Cada carro (processo) está em um pedaço da estrada e precisa atravessar várias pontes (recursos) para chegar ao destino. O problema é que, como os carros estão em lugares diferentes (servidores diferentes), fica muito mais difícil saber exatamente onde está o engarrafamento. É como tentar resolver um trânsito olhando só um pedaço da cidade: pode ter travado em outro ponto e você nem vê. Por isso, o deadlock em sistemas distribuídos é mais complicado de detectar e resolver. 🛠 Estratégias para lidar com deadlock Ignorar o deadlock É como fingir que o trânsito nunca vai travar. Windows e Linux fazem isso: se travar, reinicia. Funciona porque o problema é raro, mas se acontecer… paciência. Prevenir o deadlock (mudar as regras para evitar que aconteça): Remover exclusão mútua → deixar os recursos compartilhados (ex.: várias pessoas podem ler o mesmo arquivo ao mesmo tempo). Remover preempção → se alguém segurar o recurso, o sistema força a liberar (como um policial mandando um carro dar ré). Remover retenção e espera → o processo só começa se já tiver todos os recursos reservados. (Quase impossível na prática, e pode gerar starvation). Remover espera circular → impor uma ordem fixa para pedir recursos. (Ex.: todo mundo pede primeiro a ponte 1, depois a ponte 2). Evitar o deadlock O sistema tenta prever os recursos que serão usados antes de começar. É como só deixar o carro entrar na estrada se tiver certeza de que ele consegue atravessar todas as pontes sem travar. Detectar o deadlock Deixa o problema acontecer, mas fica de olho. Quando percebe o engarrafamento, “chuta” um carro para fora (mata um processo) e libera os outros. 🍽 Starvation (inanição) É parecido, mas diferente: Imagine uma fila de restaurante em que sempre deixam passar os clientes VIPs na frente. Quem está no fim da fila (baixa prioridade) nunca é atendido, porque sempre chega alguém mais importante. ➡ Isso é o starvation. Ocorre quando um processo de baixa prioridade fica esperando indefinidamente por um recurso que sempre vai para os de maior prioridade. 🔧 Solução: aging (envelhecimento) → quanto mais tempo o processo espera, mais sua prioridade aumenta, até ser atendido. ⚖ Comparação rápida Deadlock Starvation Todos os processos ficam travados Só os de baixa prioridade ficam travados Recursos parados, ninguém anda Recursos continuam sendo usados, mas sempre pelos mais “fortes” Prevenir mexendo nas 4 condições do deadlock Prevenir com aging (aumentando prioridade com o tempo) 👉 Em resumo: Deadlock é como um engarrafamento total, ninguém anda. Starvation é como uma fila injusta, só alguns ficam parados enquanto outros continuam.