[Java Concurrency] oferta 11.P6 passe por porque eu não entendo o princípio da sincronizado


uso

chave sincronizados é um dos meios mais comuns de sincronização de segmento programação simultânea, fecho pessimista sincronizadas, e o seu papel é triplo:

Mutuamente exclusivas: assegurar fio acesso mutuamente exclusivas bloqueio geração de sincronização é automaticamente liberado, com uma multiplicidade de fios operacionais de código ou função bloqueia deve adquirir a fila de bloqueio,
visibilidade: modificar as variáveis compartilhadas para garantir fio oportuna visível para adquirir a operação de bloqueio é concluída os dados serão liberados para a memória compartilhada
ordenação: efetivamente resolver o problema da reordenação, a sua utilização também tem três:
um exemplo modificado do método de
modificação de um método estático de
modificar bloco
1. o exemplo modificado de um método

sincronizado palavra-chave na frente do papel do método para o método de bloqueio, de facto, este é o objecto de bloqueio padrão.

classe Thread1 os implementos do Runnable {public
    // recurso compartilhado (recurso crítico)
    static int i = 0;
    // se a chave não está sincronizado, a saída é inferior a 20000
    pública sincronizado Aumento void () {
        I ++;
    }
    pública void run () {
        for (int J = 0; J <10000; J ++) {
            Aumento ();
        }
    }
    public static void main (String [] args) throws InterruptedException {
        Thread1 T = new new Thread1 ();
        o T1 rosca = new new thread (T);
        o segmento T2 = o fio novo novo (T);
        t1.start ();
        t2.start ();
        t1.join (); // espera para o acabamento thread principal t1
        t2.join (); // espera para o principal t2 fio terminou
        System.out. o println (I);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


2. método estático Modificado

sincronizada ou modificação no método, mas a modificação é um método estático, equivalente ao objecto Classe está bloqueado,

    classe Thread1 {public
    // recurso compartilhado (recurso crítico)
    static int i = 0;

    // Se não sincronizado palavra-chave, a saída é inferior a 20000
    public void Aumento sincronizado estático () {
        I ++;
    }

    public static void main (String [] args) throws InterruptedException {
        o segmento T1 = new new Thread (new new o Runnable () {
            public void run () {
                for (int J = 0; J <10000; J ++) {
                    Aumento ();
                }
            }
        });
        o segmento nova novo o segmento T2 = (a Runnable novo new () {
            @Override
            public void run () {
                for (int J = 0; J <10000; J ++) {
                    Aumento ();
                }
            }
        });
        t1.start () ;
        t2.start ();
        t1.join (); // espera para o acabamento thread principal t1
        t2.join (); // espera para o segmento principal é t2 acabado
        System.out.printlnl (i);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


3. O bloco modificado

Para uso é para modificar os parâmetros modificados em intervalos sincronizados com as funções que, em comparação com a função de bloqueio dessa faixa é menor, você pode especificar que o bloqueio do objeto.

classe Thread1 os implementos do Runnable {public
    // recurso compartilhado (recurso crítico)
    static int i = 0;

    @Override
    public void run () {
        for (int J = 0; J <10000; J ++) {
            // obter Cadeia de bloqueio classe
            a sincronizado (String.class) {
                I ++;
            }
        }
    }

    public static void main (String [] args) throws InterruptedException {
        Thread1 t = new Thread1 ();
        Tópico t1 = new Thread (t);
        Tópico T2 = new Thread (t);
        t1.start ();
        t2.start ();
        t1.join ();
        t2.join ();
        System.out.printlnl (i);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

resumo:

Exemplos de método modificado sincronizado, multi-threaded acesso simultâneo, apenas um segmento de introduzir, obter um objecto embutido bloqueio, outros segmentos são bloqueados aguardando, mas ao mesmo tempo o segmento pode ainda aceder a outros métodos.
modificação sincronizado de métodos estáticos, multi-threaded acesso simultâneo, apenas um segmento de introduzir, obter bloqueio classe, outros segmentos são bloqueados aguardando, mas ao mesmo tempo o segmento pode ainda aceder a outros métodos.
bloco de código sincronizado modificado, multi-threaded acesso simultâneo, apenas um segmento de entrada, em conformidade com os suportes ou objecto de classe, os correspondentes ferrolhos de classe objecto ou embutido de bloqueio
para cada classe tem uma classe de fechaduras, cada classe objetos também tem incorporado um bloqueio, eles interferem um com o outro, o que significa que um segmento pode obter o bloqueio e embutido fechaduras e classe de objectos instanciar, quando o método de acesso tópicos synchronzied não modificada, não precisa de adquirir um bloqueio, Portanto, nenhuma obstrução.
o tubo

O tubo (em Inglês: Monitores, também conhecido como um monitor) é um conceito muito importante no sistema operacional, o tubo na verdade se refere à gestão de variáveis ​​compartilhadas durante a operação e gestão de variáveis ​​compartilhadas. Intermediários jogar um pouco significam, um grupo de gestão de processos de objetos de tubos, vários segmentos no mesmo tempo, apenas um segmento para o acesso dessas coisas.

O tubo pode ser visto como um módulo de software, que é partilhada por estas variáveis e variáveis compartilhadas operação de embalagem, para formar um módulo funcional com uma determinada interface, processar o tubo pode ligar a implementar nível do processo de controle de concorrência.
Processo só pode ter uso exclusivo do tubo, isto é, quando um processo utilizando o tubo, um outro processo deve esperar. Depois de um processo terminado de usar o tubo, ele deve liberar o tubo e um processo para esperar por um processo de tubo de wake-up.
O tubo é relativamente simples de resolver o problema de exclusão mútua, a operação das variáveis compartilhadas e variáveis compartilhadas são encapsulados em uma classe

Quando um segmento A e necessidade segmento B para obter uma contagem variável compartilhada, você precisa chamar a métodos get e set, e métodos get e set é garantir mutuamente exclusivas, apenas um segmento para garantir que cada visita.
gerente de distribuição, cada parte de um gerenciamento intermediário habitação em segunda mão,

A mediação é o tubo.
Uma pluralidade de casas em segunda mão são uma gestão intermediário, gestão de processos é um tubo com vários recursos do sistema.
Vários clientes é equivalente a vários segmentos.
O princípio subjacente Synchronzied

análise do cabeçalho objecto

Sabemos que um objeto na área de heap Java é criado na área de memória da JVM, depois que o objeto é criado consiste em três partes.

Possui três partes da seguinte forma:

Preenchimento de dados: Desde a máquina virtual start-request endereço objeto deve ser um inteiro múltiplo de 8 bytes. dados de enchimento não necessitam de estar presentes, apenas para o alinhamento de bytes.
Exemplos de variáveis: o armazenamento de informações de atributo, tais como dados, informações de atributo incluindo a classe principal, esta memória de 4 bytes alinhados.
cabeçalho do objecto: inclui duas partes
Klass ponto (tipo de ponteiro): o objecto é um ponteiro para a sua classe de metadados, a máquina virtual é determinada pelo apontador, que é um exemplo da classe de objecto.
Mark Palavra (campos marcadores): Esta secção de armazenamento de dados de operação do si, objecto, tal como um código de hash, a idade gerações GC, bandeiras de estado de bloqueio, os ponteiros, etc. fechaduras, que são parte do tamanho dos dados no 32 e 64 bits de máquina virtual é um 32 e 64 bits, tendo em conta a eficiência do espaço da máquina virtual, Mark Palavra é concebido como um estruturas não-fixos de dados para armazenar tanta informação em um espaço muito pequeno, ele vai ser multiplexado de acordo com seu estado de espaço de armazenamento de objeto ( da mesma forma com ConcurrentHashMap na bandeira), os detalhes como mostrado abaixo:
marca de estado de palavra representa um pouco como se segue:

Quer ou método de modificação bloco de código sincronizado, a sincronização é conseguida pela realização de um bloqueio modificada do objecto, se o objecto está sincronizado cabeçalho de bloqueio objecto Mark Palavra. travamento leve e enviesada que fechaduras após Java6 de bloqueio sincronizado para optimizar a nova adição, aqui analisamos bloqueio pesado muitas vezes se diz sincronizado bloqueio objecto, a bandeira de bloqueio é 10, que é um ponteiro para o monitor objeto (também conhecido como o monitor de tubo ou de bloqueio) do endereço de início. Cada objeto tem um monitor associado a ele.

 

desmontagem Ver

Ex objeto de análise monitor de nós primeiro bloco que nível de instrução linguagem de montagem através do método de sincronização olhar desmontagem com o método de sincronização.

{Classe SynchronizedTest pública
    public void o doSth sincronizado () {
        System.out.println ( "o Olá Mundo");
    }
    public void doSth1 () {
        a sincronizado (SynchronizedTest.class) {
            System.out.println ( "o Olá Mundo");
        }
    }
}
. 1
2
3.
4.
5.
6.
7.
8.
9.
10
a SynchronizedTest javac então decompilado .Java ver javap -c SynchronizedTest assembler instruções são as seguintes:

 pública sincronizado vazio doSth ();
    descritor: () V
    bandeiras: ACC_PUBLIC, ACC_SYNCHRONIZED //这是重点方法锁
    cupom:
      pilha = 2, os moradores = 1, args_size = 1
         0: getstatic # 2                 
         3: LDC # 3   
         5: invokevirtual # 4                 
         8: retorno

  public void doSth1 ();
    descritor: () V
    as bandeiras: ACC_PUBLIC
    Código:
      .. Stack = 2, cerca de habitantes = 3, args_size 1 =
         . 0: LDC 5 #                
         2: DUP
         . 3: astore_1
         . 4: // inserir o método de sincronização monitorenter
         5: getstatic # 2                 
         8:.. LDC 3 #                 
        10:. invokevirtual 4 #               
        13 é: aload_1
        14: o método de sincronização normal de saída monitorexit //
        15: GOTO 23 é
        18 é: astore_2
        . 19: aload_1
        20 é: o saída monitorexit // método de sincronização anormal
        21 é: aload_2
        22 é: athrow
        23: retorno
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 é
13 é
14
15
16
. 17
18 é
. 19,
20 é
21 é
22 é
23 é
24
25
26 é
27
28
29
30
31 é
que podemos ver o compilador código de bytes de Java gerado por nós. No processo para a doSth e doSth1 ligeiramente diferente. Isso quer dizer. JVM método diferente para a sincronização de processamento e código de sincronização do bloco. Para o método de sincronização, JVM ACC_SYNCHRONIZED empregue para alcançar marcador de sincronização. Para o bloco sincronizado. Usando o monitorenter JVM, monitorexit duas instruções para conseguir a sincronização.
ACC_SYNCHRONIZED

O método de sincronização de fase está implícita. Haverá uma piscina ACC_SYNCHRONIZED método de sincronização marca constante. Quando um thread para acessar um método, ele verifica se há ACC_SYNCHRONIZED, se configurado, você precisa para obter o bloqueio do monitor, e começa método de execução, e em seguida, liberar o bloqueio do monitor após o método é executado. Então, se os outros segmentos para executar o método de solicitação, porque o monitor não é possível obter um bloqueio para ser bloqueado para viver. Note-se que, se durante a execução do método, a ocorrência de anormalidade, eo método interno não tratar a exceção, o bloqueio do monitor é automaticamente liberado antes a exceção é lançada para fora do método.
monitorenter com monitorexit

Pode ser entendido como um bloqueio monitorenter execução de instrução, monitorexit execução entendido para libertar o bloqueio. Cada objecto mantém um registo do número de vezes contador está bloqueada. objeto desbloqueado deste contador é 0, quando um segmento para adquirir o bloqueio (execução monitorenter), o contador é incrementado de um, quando a fechadura do objectivo de obter o mesmo fio de novo, o contador de incremento de novo. Quando o mesmo segmento libera o bloqueio (execução de instrução monitorexit), o contador é diminuído novamente. Quando o contador é zero. A trava é liberada, os outros segmentos podem adquirir um bloqueio.
Conclusão: O método de sincronização e uma parte inferior do bloco de código de sincronização são alcançados por um monitor de sincronização.
A diferença: o modo de sincronização é conseguida por um método do access_flags ACC_SYNCHRONIZED bandeira estiver definido, o bloco de código de sincronização é realizado por monitorenter e monitorexit.

monitor de determinação

Sabemos que cada objeto é associado a um monitor, eo monitor pode ser thread possui ou lançamento, o Java Virtual Machine (HotSpot) em, monitor ObjectMonitor alcançado a sua estrutura de dados primário é a seguinte (localizado HotSpot Virtual ObjectMonitor Fonte Máquina arquivo .hpp, implementação C ++).

ObjectMonitor () {
    O _count = 0; // número de registros
    _recursions = 0; // número de reentrada bloqueio
    _owner = NULL; // ObjectMonitor fio objeto preensão ponto
    _WaitSet = NULL; // chamada para a espera, o fio pode ser adicionada para _WaitSet
    _EntryList = NULL; // espera por uma rosca para adquirir o bloqueio, são adicionados à lista
}
1.
2
3.
4.
5.
6.
7.
a operação do monitor é a seguinte:

Por um método para modificar sincronizado (bloco) é:

Quando vários segmentos aceder ao processo, em seguida, estes fios serão primeiro colocar fila _EntryList, em seguida, o fio é bloqueado estado
depois de um fio obtido quando o objeto do monitor, em seguida, ele pode entrar no estado de funcionamento, o bloco de realização do método, no momento , _owner ObjectMonitor objeto aponta para o segmento atual, _count mais 1 indica que o alvo atual é um thread obtém o bloqueio.
Quando o estado de execução é chamado de espera fio () método, então as atuais versões de rosca do objeto monitor, entra no estado de espera, objeto _owner ObjectMonitor torna-se nulo, _count menos 1, enquanto o segmento entra na fila _WaitSet até que as chamadas de rosca notificar método () acordar o fio, o fio entra na fila _EntryList, re-entrar na competição para a área de bloqueio _owner.
Se o segmento atual está terminado, ele também pode monitorar o lançamento do objeto, _owner ObjectMonitor objeto torna-se nulo, _count menos 1.
Desde o bloqueio monitor (monitor) é dependente do sistema operacional subjacente Mutex bloqueio alcançado, e precisa ser convertido a partir do modo de usuário para modo kernel ao alternar entre tópicos que operam implementação do sistema, a transição entre um estado requer relativamente longo tempo, custo de tempo é relativamente alta, razão pela qual no início sincronizado razões de baixa eficiência. Felizmente, após o oficial de nível JVM Java 6 Java a partir da optimização sincronizado maior, finalmente, melhorar significativamente, Java após 6, a fim de obter e fechaduras de libertação para reduzir o consumo de desempenho causada pela introdução do conceito de escalonamento de bloqueio.

escalonamento de bloqueio

Há quatro estado sincronizado bloqueio, sem bloqueio, tendem a fechadura, trancar leve de bloqueio, pesado. Estes estados vão competir com o bloqueio estado escalado pode atualizar, mas não pode voltar, mas o estado de bloqueio tendenciosa pode ser redefinido para o estado livre de bloqueio.

fecho enviesada

Porque depois de HotSpot autor de um grande número de estudos descobriram que a maior parte do tempo, não há contenção de bloqueio, muitas vezes várias vezes para obter um fio com um bloqueio, por isso, se cada vez que a concorrência vai aumentar o bloqueio de número não é necessário pagar o preço, a fim de reduzir o custo de aquisição do bloqueio, o bloqueio foi introduzido viés.
A idéia central:

Se um segmento obtém um bloqueio, em seguida, o bloqueio para entrar no modo de polarização, onde a estrutura Mark Palavra também torna-se polarizado estrutura de bloqueio, quando o fio novamente solicitar uma fechadura, e não mais de sincronização, isto é, o processo de aquisição do bloqueio, de modo que eliminando a necessidade de um grande número de operações relativas à aplicação de bloqueios, que irá fornecer o desempenho do programa. Assim, não há nenhuma ocasião para contenção de bloqueio, tendenciosa bloqueio bons resultados de otimização, afinal de contas, é provável que seja a mesma repetidamente aplicar o mesmo bloqueio de segmento. Mas, quanto mais intensa competição por lugares fechaduras, viés de bloqueio sobre o fracasso, porque esta situação é susceptível de bloquear uma thread para cada aplicativo são diferentes e, portanto, não deve ser usado tendenciosa bloqueio Neste caso, de outra forma seria desperdiçado, necessidade de prestar atenção que tendem a bloquear após o fracasso, e não irá expandir bloqueio imediato dos pesos pesados, mas a primeira atualização para o fechamento leve.
processo específico: quando uma blocos de rosca e obter um objeto de bloqueio código de acesso, o bloqueio é gravado no cabeçalho threadID objecto java inclinado e um quadro de pilha não é activa porque o fecho enviesada libertar o bloqueio, de modo que depois que o segmento 1 adquire o bloqueio novamente quando, necessidade de comparar o atual segmento ThreadID e objetos Java cabeçalho threadID são os mesmos, se o mesmo (ou 1 fio adquire os objetos de bloqueio), você não precisa de bloqueio, desbloqueio usando CAS, se não (outros tópicos, tais como fio 2 para competir objeto de bloqueio bastante tendenciosa de armazenamento de bloqueio até que não vai tomar a iniciativa de lançar o fio ThreadID 1), então a necessidade de ver a cabeça de gravação objeto thread Java 1 está vivo, se não a sobrevivência, em seguida, bloquear o objeto é redefinido para o estado livre de bloqueio, outros segmentos ( rosca 2) pode ser configurado para competir bloqueio tendenciosa, se vivo, em seguida, encontrar imediatamente o segmento (thread 1) das informações quadro de pilha, se você ainda precisa de continuar a manter este objeto de bloqueio, em seguida, faz uma pausa o atual segmento 1, cancelar tendenciosa bloqueio, atualização é um bloqueio leve, se um fio não usa o objeto de bloqueio, em seguida, o estado do objecto de bloqueio para o estado livre de bloqueio, re-polarização Novo segmento.

bloqueio leve

bloqueio leve não é muito considerando o objeto de bloqueio fio competição, e o fio que segura o tempo de bloqueio não é longa cena. Porque o segmento de bloqueio precisa CPU do modo de utilizador para o modo kernel, o custo do maior, se apenas bloqueado logo após o bloqueio será liberado, e que este preço é um pouco mais mal do que bem, por isso desta vez eles simplesmente não bloquear esta discussão e deixá-lo girar esta aguardando a liberação de bloqueio.

Princípio com o upgrade:
Thread 1 vai primeiro objeto alvo MarkWord espaço de bloqueio cabeça para armazenar uma cópia do fio de bloqueio de registo quadro 1 pilha criado (chamado DisplacedMarkWord) adquirir um bloqueio leve, em seguida, usar o CAS substituindo o conteúdo do objecto de cabeçalho bloqueia a ficha de armazenamento rosca endereço (DisplacedMarkWord);

Se a rosca 1 copiado cabeçalho objecto ao mesmo tempo (antes de o fio 1CAS), segmento 2 também está preparado para adquirir o bloqueio, copiar o cabeçalho objecto para bloquear o fio espaço de gravação 2, mas quando a rosca 2CAS encontrado o fio 1 tem o cabeçalho objecto alterada, CAS rosca 2 falhar, então o segmento 2 irá tentar usar bloqueios de rotação de segmentos de espera 1 para libertar o bloqueio. bloqueio de rotação é simplesmente deixar o fio 2 continuamente a tentar obter uma objetos de bloqueio no ciclo CAS.

Mas se você girar muito tempo não funciona, porque a rotação é consumir CPU, então o número de rodadas é limitado, por exemplo, 10 vezes ou 100 vezes, se o número de vezes para girar o fio 1 não tenha liberado o bloqueio, ou Thread 1 ainda está em execução, ainda 2 fios spin-espera, por isso desta vez ele irá se expandir pesado bloqueio bloqueio leve. Além pesado bloquear o segmento que possui o bloqueio são bloqueados, impedindo o ocioso CPU.


PS: Nesta processo geral fechaduras têm uma boa WC explicar.

eliminação de bloqueio

Eliminando o bloqueio é outra otimização bloqueio máquina virtual, essa otimização é mais completo, máquinas virtuais Java em execução no contexto de compilador JIT digitalização, o bloqueio não pode remover compartilhada competição de recursos, eliminando, desta forma, exceto que não é o bloqueio necessário, o pedido de bloqueio pode salvar sentido tempo, sabemos que StringBuffer é thread-safe, que contém existe um bloqueio, mas se usarmos StringBuffer dentro da função, em seguida, o código irá bloquear automaticamente Oh libertado após JIT.

Comparação segue:

Vantagens Desvantagens bloquear estado cena Aplicável
tendenciosa bloqueio desbloquear fechadura sem consumo adicional, a diferença de tempo com o nanossegundo método assíncrono se competindo tópicos e mais, vai trazer bloqueios adicionais consumo revogação basicamente nenhuma outra sincronização de threads cena competição
bloqueio leve segmentos concorrentes não será bloqueado, mas o spin pode aumentar a velocidade de resposta se o programa tem sido incapaz de obter uma pequena quantidade de consumo de CPU irá girar o fio da competição, tem o tempo de bloqueio é não muito tempo, a busca da velocidade de resposta
de bloqueio pesado o fio não levar a concorrência de CPU fio de rotação é bloqueada com o consumo de recursos da CPU, tempo de resposta é longa bloquear muitos segmentos para competir, fechaduras corte mantidos por um longo tempo, a busca de rendimento quando
PS: implementação subjacente ReentrantLock é dependente de instruções da CPU especiais, tais como envio de comandos bloquear e desbloquear instruções, os usuários não precisam comutação de modo de modo e núcleo, a eficiência é elevada (em que os princípios subjacentes da volátil e semelhantes), e sincronizado pela parte inferior de bloqueio do monitor (monitor) é dependente do sistema operativo subjacente Mutex necessidade de bloqueio para o modo de troca de usuário e modo de núcleo, a eficiência de ele será menor.

Bloqueio fluxograma escalada

A última atualização oferta de bloqueio para ampliar unbelievableme tirada:


referência

A compreensão em profundidade das sincronizado
blogue destacada Ali especialista
----------------

link original: https: //blog.csdn.net/qq_31821675/java/article/details/105298334
Direitos de autor: artigo original 'SoWhat1412' Bloggers, siga o CC 4.0 BY-SA acordo de direitos autorais, reproduzido, por favor anexar o link fonte original e esta declaração.

https://jlwz.cn/userinfo-1000-443397.html
https://jlwz.cn/bbs/userinfo.aspx?touserid=40732&backurl=
https://jlwz.cn/userinfo-1000-443398.html
https: //jlwz.cn/userinfo-1000-443401.html
https://jlwz.cn/userinfo-1000-443405.html
https://www.iyamusic.com/user/143753
https://www.iyamusic.com / user / 143807
https://www.iyamusic.com/user/143809
https://www.iyamusic.com/user/143812
https://www.iyamusic.com/user/143815
http: //www.92kk .com / m / zf7652051 /
http://www.92kk.com/m/zf7652051a/
http://www.92kk.com/m/zxcfghrnb
http://www.92kk.com/m/hgffrt4rw
http: / /www.92kk.com/m/sgsdfhkf
https://streetvoice.cn/zf7652051/
https://streetvoice.cn/zcasdgadas/
https://streetvoice.cn/fdsgffghgxc/
https://streetvoice.cn/nvcbdh/
https://streetvoice.cn/fhvxdm/

Acho que você gosta

Origin www.cnblogs.com/dasdfdfecvcx/p/12633659.html
Recomendado
Clasificación