46
Boas Práticas de Programação Concorrente Evitando surpresas inconvenientes Ronny Moura

Programação Boas Práticas de Concorrente Exemplos de erros comuns da programação concorrente Exemplo de resolução de erro de concorrência no SIGRH. Race Condition É uma condição

Embed Size (px)

Citation preview

Boas Práticas de Programação Concorrente

Evitando surpresas inconvenientes

Ronny Moura

Súmario

● Principais problemas da programação concorrente e os mecanismos Java para resolvê-los.○ Race condition(synchronized, Lock e Atomic);○ Visibilidade (volatile)

● Exemplos de erros comuns da programação concorrente● Exemplo de resolução de erro de concorrência no SIGRH.

Race Condition

É uma condição especial que pode ocorrer dentro de uma região critica( trecho de código executado por múltiplas threads) onde a sequência da execução das threads pode ocasionar inconsistência nos valores dos recursos alterados dentro da região crítica.

Race Condition

Race Condition

O código no método add() é um exemplo de uma região crítica. Como sabemos, o método não é executado de forma atomica pela JVM, ao invés é dividido em instruções, tais como ler o contador da memória dentro de um registrador, adicionar o valor para o registrador e por último escrever o registrador na memória. Agora imagine duas threads, A e B, executando add() na mesma instância de Counter.

Race Condition

Race Condition

A duas threads adicionaram os valores 3 e 2 para o contador, assim era de se esperar que o valor do contador após a execução das duas threads fosse 5. No entanto, como a execução das thread é intrelaçada, o resultado é diferente.

Como prevenir?

Para prevenir a race condition deve-se assegurar que a região crítica será executado por uma instrução atômica, ou seja, deve haver uma exclusão mútua na execução das threads dentro da região crítica. Isso implica que uma thread não executará a região crítica até a outra thread deixar a mesma. Uma estratégia eficáz para resolver o problema é o mecanismo de lock, que consiste de uma thread necessitar adquirir o lock para poder entrar na região crítica. Quando uma thread está com o lock, as outras têm que esperar a liberação do lock para que uma delas possa adquiri-lo e executar na região crítica.

Synchronized

Java prover um mecânismo de lock por meio da palavra-chave synchronized.

Existem duas formas de usar o mecânismo: sincronizando o método ou o bloco.

Synchronized

Synchronized

Blocos synchronized são reentrant. Isso significa que se a thread entra em um bloco e adquire o lock para o objeto monitor do bloco( no último caso o this), então essa thread pode entrar em qualquer outro bloco que tenho o mesmo objeto monitor.

Synchronized

Lock

Lock (java.util.concurrent.locks)

Java oferece um mecanismo mais sofisticado de lock. A interface Lock permite que o desenvolvedor implemente seu próprio mecânismo de lock mas também oferece algumas implementações.

Lock (java.util.concurrent.locks)

Lock (java.util.concurrent.locks)

Atomic Variable Classes

A estratégia de Locking tem algumas desvantagens, a principal é o baixo desempenho, o que é mais evidente em um ambiente com muitas threads, devido ao overhead de troca de contexto e tempo de espera das threads. Uma estratégia mais eficiente em termos de desempenho é a CAS(Compare and Swap), que é uma estrátegia que exige suporte do hardware. Essa estratégia é dita non-blocking.

Atomic Variable Classes

Atomic Variable Classes

As Atomic Variables Classes em Java usam a estratégia CAS. AtomicInteger, AtomicLong, AtomicBoolean e AtomicReference dispõem de métodos que garantem a atomicidade das operações. Sendo assim, essas classes são thread-safe.

Atomic Variable Classes

Atomic Variable Classes

Visibilidade

Em um ambiente de multi-threads, muitas vezes uma thread não ver o valor atualizado de uma variável que está sendo compartilhada. Isso acontece porque, geralmente, cada thread mantém uma cópia local da váriavel, em cache, para melhorá o desempenho. Sendo assim, não é garantido que uma thread veja o valor atualizado, após a mudança na variável por uma outra thread.

Visibilidade

Para resolver esse problema a Java oferece o modificador volatile, que garante a visibilidade correta do valor da variável compartilhada. Usar esse modificador força a JVM a usar a memória principal(não o cache local).

Deve-se usar variáveis voláteis quando:•Escritas na variável não depende do seu próprio valor•A variável não participa do invariante com outras variáveis•Não é necessário bloquear (locking) a variável por qualquer outra razão

Visibilidade

Locking pode garantir ambas visibilidade e atomicidade, já as variáveis voláteis só podem garantir a visibilidade.

Visibilidade

Deadlock

Thread safe

Uma classe é thread safe se ela está livre de race condition.

Obs: As classes Collections não são thread-safe, no entanto na própria classe Collections existem métodos que transformam coleções non-thread-safe em coleções thread-safe.

Thread safe

Thread safe

Thread safe

Exemplos de erros comuns da programação concorrente

Retirados do stackoverflow.

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplos de erros comuns da programação concorrente

Exemplo de resolução de erro de concorrência no SIGRH

Exemplo de resolução de erro de concorrência no SIGRH

Exemplo de resolução de erro de concorrência no SIGRH

Exemplo de resolução de erro de concorrência no SIGRH

Referências

http://tutorials.jenkov.com/java-concurrency/race-conditions-and-critical-sections.html

http://tutorials.jenkov.com/java-concurrency/locks.html

http://www.vogella.com/tutorials/JavaConcurrency/article.html#concurrencyjava_synchronized

http://stackoverflow.com/questions/461896/what-is-the-most-frequent-concurrency-issue-youve-encountered-in-java

GOETZ, Java� Concurrency� In� Practice, Addison-Wesley Professional, 2006. Chapter 15. Atomic Variables and Non-blocking Synchronization.

https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html