A programação concorrente sempre foi sinônimo de desafio para grande parte dos desenvolvedores. Nesse contexto, muitos consideram que a programação orientada a objetos e a programação concorrente, depois de muito estudo e prática, deixam de ser algo tão complicado. Para a primeira, certamente a afirmação é coerente, mas como veremos ao longo do artigo, para a segunda existem controvérsias.
Quando um desenvolvedor precisa de uma nova linha de execução concorrente (thread), o máximo que ele pode fazer é criar e solicitar a execução da thread. Essa solicitação é então enviada ao escalonador, agente de baixo nível, geralmente do sistema operacional, que é responsável por coordenar a execução das threads. Tal agente é o único que tem o poder de determinar quando uma thread irá para a CPU para executar suas tarefas e por quanto tempo permanecerá lá. Portanto, a execução de threads, por natureza, é algo imprevisível; não há como determinar de antemão quando uma thread irá executar e por quanto tempo. Essa imprevisibilidade aumenta consideravelmente a complexidade de sistemas que utilizam threads, tornando difícil seu teste e a assertividade de seu processamento.
Além disso, problemas como deadlocks (vide BOX 1), que fazem com que duas ou mais threads fiquem bloqueadas “eternamente”, e o aumento de contenção, situação em que muitas threads tentam acessar uma mesma área de memória simultaneamente e apenas uma delas consegue o acesso, podem levar a inconsistências ou queda de desempenho, se não evitados ou tratados adequadamente.
Condição em que uma thread bloqueia um recurso X e precisa de um recurso Y para finalizar. Contudo, o recurso Y também está bloqueado por outra thread, que aguarda pelo recurso X para executar seu processamento.
Assim, algo que parece benéfico pode, subitamente, se tornar prejudicial. No entanto, independentemente disso, threads são inevitáveis. Imagine um servidor web que atenda apenas a uma requisição por vez (monothread). Em termos de eficiência, o desempenho de tal servidor seria pobre para o usuário, pois em situações em que o servidor receber vários acessos simultâneos pode se formar uma fila de espera na qual apenas uma requisição será atendida por vez, pela única thread que ele possui.
Já um servidor multithreading possibilita o atendimento a diversas requisições simultaneamente, o que é muito interessante em termos de experiência para o usuário. Esse e outros benefícios de um software multithreading se estendem tanto aos usuários quanto ao próprio sistema. Como exemplo, considere um programa leitor e transmissor de e-mails, no qual é possível receber e-mails enquanto outro está sendo redigido pelo usuário, sem que uma ação precise esperar a outra para acontecer. Junto a isso, há também um melhor uso dos recursos de hardware, pois com mais threads é possível deixar o sistema realizando alguma tarefa que independe de uma ação do usuário, mas que seja útil para o mesmo, como apagar e-mails que estejam na lixeira por mais de um mês.
O uso de threads leva a um modelo de programação conhecido como programação concorrente. Esse modelo é diferente de programas monothread, pois visa lidar com situações que, claro, não acontecem quando se tem apenas uma thread em execução. Por exemplo, considere uma situação em que uma variável precisa ter seu valor somado a 1 por cada thread ativa em um programa a cada um segundo. Se as threads ativas fizerem essa soma simultaneamente, o valor dessa variável poderá ficar inconsistente, pois, como dito, não há certeza de quando uma thread irá executar e nem por quanto tempo. Assim, há chances de uma thread ler o valor da variável e ser interrompida pelo escalonador logo após essa leitura, a thread seguinte ler o mesmo valor da thread anterior e, consequentemente, as duas somarem 1 ao mesmo valor da variável, o que tornaria o resultado inconsistente. Note que em um programa monothread esse problema não aconteceria.
Para evitar o problema de inconsistência na soma do exemplo citado, alguma abordagem especial deve ser aplicada, como bloquear o acesso à variável que mantém a soma e conceder a apena ...
Desbloqueie toda a DevMedia
-
+2000 artigos e vídeos
-
+40 trilhas sobre Front-end, Back-end, IA e muito mais
-
+5000 exercícios práticos
-
Mentorias ao vivo individuais
Confira outros conteúdos:
Introdução ao JDBC
Novidades do Java
Teste unitário com JUnit
Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.