Capítulo Um: Introdução
pontos de conhecimento :
- Processo é de recursos (CPU, memória, etc.) atribuído à unidade básica
- Um segmento é a unidade básica de escalonamento de CPU e expedição
- Um processo que inclui um ou mais segmentos
1, por isso a aplicação precisa de se desenvolver a partir de segmento único para multi-threaded (a partir síncrono para assíncrono)?
- a utilização de recursos . Às vezes é necessário esperar para operações externas, como entrada e saída, e não pode realizar trabalho valioso enquanto espera. Enquanto espera, para que outros programas irão melhorar a eficiência operacional.
- Fair . Vários usuários ou programas podem ter igual prioridade nos recursos do sistema. Permita-lhes para compartilhar fatia de tempo computador através de melhores formas mais desejáveis do que os próximos extremidades programa após o início de um programa.
- Conveniente . Escrever alguns procedimentos, de modo que cada um deles executa uma única tarefa e fazer a coordenação necessária, que é melhor do que escrever um programa para executar todas as tarefas mais fácil e mais satisfatório.
Capítulo II: thread-safe
de um objeto estado é os seus dados . Escrever código thread-safe, em essência, é a gestão do estado visita (estado), e muitas vezes são compartilhadas , a variável estado.
A chamada de partilha , refere-se a uma variável pode ser acedida por vários segmentos; o chamado variável refere-se ao valor da variável pode mudar durante o seu ciclo de vida. segurança de segmentos de nossa discussão parece ser sobre o código, mas nós realmente precisamos fazer, é para proteger os dados em acesso simultâneo não é controlado.
Na ausência de sincronização adequada, se vários segmentos acessar a mesma variável, o programa existe risco. Há três maneiras de corrigi-lo:
- Faça variáveis não cross-fio compartilhada;
- Uma variel de estado é imutável; ou
- acesso síncrono em quaisquer variáveis de estado de tempo.
Thread-safe definição:
Quando vários segmentos acessar uma classe, se não considerar programação alternativa e execução nestes tópicos no ambiente de tempo de execução, e não requer sincronização adicional e o código de chamada não faz outro comportamento coordenação desta classe ainda está correto em seguida, chamar essa classe é thread-safe de.
objetos apátridas são sempre thread-safe.
Tópico insegurança operação complexa
Leia - mudança - write (ler-modificar-escrever)
@NotThreadSafe
public class UnsafeCountingFactorizer implements Servlet {
private long count = 0;
public long getCount() { return count; }
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
++count;
encodeIntoResponse(resp, factors);
}
}
Verifique o prazo (check-act)
@NotThreadsafe
public class LazyInitRace {
private Expensive0bject instance = null;
public ExpensiveObject getInstance() {
if ( instance == null ) {
instance = new Expensive0bject();
}
return instance;
}
}
A fim de assegurar, operações de thread-safe "check-run" (como inicialização lenta) e ler - modificar - operações de gravação (como incremento) deve ser atômica. Vamos "corrida de controle" e "Leia - mudança - write" todo o processo de execução de uma operação complexa: A fim de garantir o funcionamento thread-safe devem ser executadas atomicamente.
Na próxima seção, vamos considerar o uso de built-atômicas mecanismos de Java - fechaduras. Agora, vamos corrigir esse problema de outras maneiras - usando as classes thread-safe existentes.
@ThreadSafe
public class CountingFactorizer implements Servlet {
private final AtomicLong count = new AtomicLong(0);
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
count.incrementAndGet();
encodeIntoResponse(resp, factors);
}
}
java.util.concurrent.atomic
O pacote inclui variáveis átomos (variável) atómica classes para implementar estados atómicas das referências de objeto de conversão e digitais. Os long
tipos alternativos de contra- AtomicLong
tipos, podemos garantir que todo o acesso ao estado de balcão são atômica. Contadores são thread-safe.
bloqueio interno
Java fornece um mecanismo atômicas built-in bloqueio forçado: synchronized
. Um synchronized
bloco que tem duas partes: o objeto de bloqueio é referenciada, e o bloco de bloqueio de código de protecção.
Cada objecto de Java pode desempenhar um papel bloquear implicitamente para sincronização; estes embutido fechaduras é chamado bloqueio interior (fechaduras intrínsecas) ou um monitor de bloqueio (monitor de bloqueios).
segmento de execução para entrar synchronized
e sair através do normal, independentemente do caminho de controle, ou jogado a partir do bloco, as roscas estão a dar-se; irá bloquear automaticamente até que o fecho synchronized
é libertado automaticamente quando o bloco de controlo de bloqueio.
A única maneira de obter dentro da fechadura é: O método de inserção do bloco de sincronização ou proteger o bloqueio interno.
bloqueio interno jogado em Java mutex (bloqueio de exclusão mútua, também chamada de exclusão mútua) papel, o que significa que, no máximo, apenas um thread pode possuir o bloqueio, quando a rosca Um está tentando solicitar um B ocupada bloqueio, rosca Um imperativo esperar ou bloco até B libera-lo. Se B não libera o bloqueio, A vai esperar para sempre.
Re-entrada (reentrância)
Quando um segmento solicita outro segmento já tem um bloqueio, o segmento solicitante será bloqueado. No entanto, bloqueio interno é re-introduzido, de modo que o fio em seu próprio tempo tentando obter a posse da fechadura, o pedido será bem sucedido.
meios de reentrada que o pedido é baseado em " por thread (por thread)", em vez de " por chamada (por invocação)" é.
Ela é alcançada por reentrada a uma contagem pedido associado a cada bloqueio (contagem de aquisição) e um fio possui. Quando a contagem é 0, que o bloqueio está desocupado.
Quando um segmento solicita o bloqueio desocupado, a JVM gravação bloqueio ocupante, ea contagem do pedido é definido como 1. Se o mesmo segmento solicita novamente o bloqueio contagem é incrementada; blocos de sincronização cada segurando saídas de rosca, o valor do contador é diminuído. Até o contador chegar a zero, o bloqueio será liberado.
/**
* 如果该锁不是可重入的,代码将死锁
*/
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
@Override
public synchronized void doSomething() {
super.doSomething();
}
}
Para cada variável de estado variável pode ser acessada por vários segmentos, se todo o acesso que tem desempenhado na implementação da linha com um bloqueio, caso em que, nós chamamos esta variável é a proteção de bloqueio.
Cada variável variáveis compartilhadas precisa bloquear protegido por apenas uma determinada.
Ajuste
synchronized
o tamanho do bloco, de modo a alcançar um equilíbrio entre segurança e desempenho.
Cálculo ou algumas operações demoradas, como o console ou uma rede de I / O, é difícil rapidamente. Não bloquear posse durante a execução dessas operações.