Conhecimento aprofundado de vários bloqueios em Java (abaixo)

Bloqueios pessimistas, bloqueios otimistas, bloqueios de rotação, bloqueios tendenciosos, bloqueios leves, bloqueios pesados ​​estão na primeira parte: uma compreensão aprofundada de vários bloqueios em Java (parte 1)

Vamos falar sobre outras fechaduras hoje:
Conhecimento aprofundado de vários bloqueios em Java (abaixo)

4. Bloqueio justo VS bloqueio injusto

A imparcialidade dos bloqueios é relativa à ordem em que os bloqueios são adquiridos.

Fair lock: a ordem em que o fair lock adquire o bloqueio está em conformidade com a sequência de tempo absoluta da solicitação. Os threads que não adquiriram o bloqueio serão organizados em uma fila de bloqueio, ou seja, FIFO. A desvantagem é que a taxa de transferência é muito baixo, porque além do primeiro na fila de espera Um thread, todos os outros threads serão bloqueados, e a ativação do thread bloqueado pela CPU também requer muita sobrecarga.

Bloqueio injusto: Um bloqueio injusto ocorre quando vários threads tentam adquirir o bloqueio diretamente e esperarão até o final da fila de espera se não conseguirem adquiri-lo. Mas se o bloqueio estiver apenas disponível neste momento, então este encadeamento pode adquirir diretamente o bloqueio sem bloqueio, então um bloqueio injusto pode ocorrer após o encadeamento que está aplicando o bloqueio adquirir o bloqueio primeiro. A vantagem dos bloqueios injustos é que eles podem reduzir a sobrecarga de invocar threads e a eficiência geral do throughput é alta, porque os threads têm a chance de obter bloqueios diretamente sem bloquear e a CPU não precisa despertar todos os threads. A desvantagem é que os threads na fila de espera podem morrer de fome ou esperar muito tempo antes de obter o bloqueio.

Dê uma olhada em como ReentrantLock implementa bloqueios justos e injustos:

Conhecimento aprofundado de vários bloqueios em Java (abaixo)

Comparando o código-fonte, podemos descobrir que os bloqueios justos têm mais um método para julgar do que os bloqueios injustos:
hasQueuedPredecessors ()

 public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

O que hasQueuedPredecessors () faz é determinar se o nó atual na fila de sincronização tem um nó predecessor. Se retornar verdadeiro, indica que outros encadeamentos adquiriram o bloqueio anteriormente, então ele precisa aguardar o nó anterior para liberar o bloqueio antes de ter a chance de continuar adquirindo o bloqueio.

Resumindo, fair lock é sincronizar a fila para perceber que vários threads adquirem bloqueios na ordem em que se aplicam para bloqueios, alcançando assim a justiça. Quando o bloqueio injusto é bloqueado, a espera na fila não é considerada, e o bloqueio é tentado diretamente para obter o bloqueio, portanto, o bloqueio é obtido após a aplicação do aplicativo.

5. Bloqueio reentrante VS bloqueio não reentrante

Bloqueio reentrante: Quando o mesmo objeto é adquirido pelo thread fora do método, o método que entra na camada interna do método irá automaticamente adquirir o bloqueio, e não será bloqueado porque o método externo ou interno não libera o bloqueio. Java ReentrantLock e synchronized são bloqueios reentrantes.Uma vantagem dos bloqueios reentrantes é que os bloqueios podem ser evitados até certo ponto. Um código simples para explicar:

public class Man {

    public synchronized void watch(){
        say();
    }

    public synchronized void say(){
        System.out.println("happy new year");
    }
}

Os dois métodos da classe Man são decorados com synchronized. O método eat () é chamado no método watch (). Como o bloqueio sincronizado é reentrante, o mesmo thread pode continuar a chamar say () chamando o método watch () método.
Se synchronized for um bloqueio não reentrante, então o mesmo thread não liberou o bloqueio (libere o monitor trazido por synchronized) quando o método watch () for chamado, e será bloqueado quando o método say () for chamado novamente. Na verdade, o encadeamento atual O bloqueio do objeto já está retido, o que não é razoável de qualquer maneira ~ Este é um bloqueio reentrante.

Basta analisar como o bloqueio reentrante ReentrantLock e NonReentrantLock
realiza o bloqueio reentrante:

Em primeiro lugar, ReentrantLock e NonReentrantLock herdam a classe pai AQS, e a classe pai AQS mantém um status de status de sincronização para contar o número de reentradas e o valor inicial do status é 0.
Quando um thread tenta adquirir um bloqueio, o bloqueio reentrante primeiro tenta adquirir e atualizar o valor do status. Se status == 0 significa que nenhum outro thread está executando o código de sincronização, então o status é definido como 1 e o thread atual inicia execução. Se status! = 0, julgue se o encadeamento atual é o encadeamento que adquiriu o bloqueio, se for, execute status + 1 e o encadeamento atual poderá adquirir o bloqueio novamente. Um bloqueio não reentrante é adquirir diretamente e tentar atualizar o valor do status atual. Se status! = 0, ele falhará ao adquirir o bloqueio e a thread atual será bloqueada.
Quando o bloqueio é liberado, o bloqueio reentrante também obtém primeiro o valor do status atual, desde que o segmento atual seja o segmento que mantém o bloqueio. Se status-1 == 0, significa que todas as operações repetidas de aquisição de bloqueio do segmento atual foram executadas e, em seguida, o segmento realmente liberará o bloqueio. O bloqueio não reentrante é definir diretamente o status para 0 após determinar que o encadeamento atual é o encadeamento que contém o bloqueio e liberar o bloqueio.

6. Bloqueio exclusivo VS bloqueio compartilhado

Bloqueio exclusivo: O synchronized e ReentrantLock mencionado no bloqueio anterior são bloqueios exclusivos, o que significa que esses bloqueios permitem que apenas um thread acesse ao mesmo tempo.

Bloqueio compartilhado: ReentrantReadWriteLock, também conhecido como bloqueio de leitura e gravação; vários threads podem ter acesso ao mesmo tempo, mas todos os threads de leitura e outros threads de gravação serão bloqueados quando o thread de gravação acessar. O bloqueio de leitura e gravação mantém um par de bloqueios, um é de leitura e o outro é de gravação. Em circunstâncias normais, o desempenho do bloqueio de leitura e gravação será melhor do que o bloqueio exclusivo, porque a maioria das cenas são leitura e gravação extra, no caso de mais leitura e menos gravação, os bloqueios de leitura e gravação têm melhor desempenho simultâneo e rendimento do que os bloqueios exclusivos.

O princípio de realização do bloqueio de leitura e gravação será atualizado em um artigo para analisar o código-fonte de ReentrantReadWriteLock.

Vá para casa no Ano Novo, decole ~

Conhecimento aprofundado de vários bloqueios em Java (abaixo)

Acho que você gosta

Origin blog.51cto.com/15075523/2606414
Recomendado
Clasificación