Concorrência
Com a concorrência procura-se o aumento do desempenho de uma aplicação através da divisão de trabalho por várias tarefas que se executam em simultâneo, tirando partido de eventuais múltiplos processadores.Sincronização
Na partilha de dados entre processadores (ou tarefas) é necessário garantir que os dados estão coerentes aquando da sua escrita.
Por outro lado,
a presença de mecanismos de sincronização pode originar contenção
quando duas ou mais tarefas tentam aceder ao mesmo recurso em simultâneo.
Se apenas existir leitura de dados partilhados por parte das tarefas concorrentes,
estes problemas não se colocam.
Cada objeto Java tem um trinco lógico próprio, que pode ser adquirido através da primitiva synchronize.
As seguintes palavras chave da linguagem são importantes:
O seguinte exemplo mostra uma utilização da sincronização em Java:
public class MySynchronizedCounter { private volatile int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } }
Os métodos increment(), decrement() e value() da classe MySynchronizedCounter estão sincronizados. Isto significa que, caso um dos 3 métodos seja invocado, o trinco do objeto é adquirido, e se houver outra tarefa a tentar aceder a qualquer um deles, ficará bloqueada à espera que o recurso/método seja libertado pela primeira invocação.
Também é possível usar o synchronize para adquirir o trinco apenas numa parte do código.
// acquire lock of object referenced by 'this' synchronize (this) { // access shared variables protected by lock } // release lock
As coleções são objetos que armazenam vários outros objetos.
Algumas das coleções mais conhecidas no Java são:
ArrayList, LinkedList, HashMap, HashSet, TreeMap, TreeSet, etc.
Cada coleção implementa uma interface que dita o tipo de acesso esperado:
Por omissão, as coleções não são sincronizadas pois este mecanismo retira desempenho ao programa.
Para situações em que é necessário sincronizar os acessos às coleções,
existem versões sincronizadas que apenas permitem um acesso de cada vez.
Para construir uma coleção sincronizada usa-se um método especial da classe Collections,
que cria a nova coleção "embrulhando" uma coleção do mesmo tipo:
List synchronizedList = Collections.synchronizedList(regularList);
Posteriormente, foram acrescentadas ao Java coleções concorrentes
(Concurrent Collections no pacote java.util.concurrent)
que são desenhadas para acesso concorrente e
que usam mecanismos “inteligentes” de bloqueio (parcial) da coleção.
Exemplos destas coleções concorrentes são:
ConcurrentHashMap, CopyOnWriteArrayList, e CopyOnWriteHashSet.
No exemplo seguinte constroí-se um mapa optimizado para acessos concorrentes:
Map<String,Object> map = new ConcurrentHashMap<>();
© Docentes de Sistemas Distribuídos,
Dep. Eng. Informática,
Técnico Lisboa