thread - synchronized objects in java




O que significa "sincronizado"? (10)

Qual é a palavra-chave sincronizada?

Os threads se comunicam principalmente compartilhando o acesso aos campos e os campos de referência de objetos se referem. Essa forma de comunicação é extremamente eficiente, mas possibilita dois tipos de erros: interferência de encadeamentos e erros de consistência de memória . A ferramenta necessária para evitar esses erros é a sincronização.

Blocos ou métodos sincronizados evitam a interferência de encadeamentos e garantem a consistência dos dados. Em qualquer ponto do tempo, apenas um thread pode acessar um bloco ou método sincronizado ( seção crítica ) adquirindo um bloqueio. Outros segmentos aguardarão a liberação do bloqueio para acessar a seção crítica .

Quando os métodos são sincronizados?

Os métodos são sincronizados quando você adiciona synchronized à definição ou declaração do método. Você também pode sincronizar um determinado bloco de código com um método.

O que significa pro gramaticalmente e logicamente?

Isso significa que apenas um thread pode acessar a seção crítica adquirindo um bloqueio. A menos que este encadeamento libere este bloqueio, todos os outros encadeamentos terão que esperar para adquirir um bloqueio. Eles não têm acesso para entrar na seção crítica sem adquirir bloqueio.

Isso não pode ser feito com mágica. É responsabilidade do programador identificar a (s) seção (ões) crítica (s) na aplicação e guardá-la de acordo. Java fornece uma estrutura para proteger seu aplicativo, mas onde e o que todas as seções a serem protegidas são de responsabilidade do programador.

Mais detalhes da page documentação do java

Bloqueios Intrínsecos e Sincronização:

A sincronização é construída em torno de uma entidade interna conhecida como bloqueio intrínseco ou bloqueio de monitor. Os bloqueios intrínsecos desempenham um papel em ambos os aspectos da sincronização: impondo acesso exclusivo ao estado de um objeto e estabelecendo ocorrências - antes de relacionamentos que são essenciais para a visibilidade.

Todo objeto possui um bloqueio intrínseco associado a ele . Por convenção, um encadeamento que precisa de acesso exclusivo e consistente aos campos de um objeto precisa adquirir o bloqueio intrínseco do objeto antes de acessá-los e depois liberar o bloqueio intrínseco quando é feito com eles.

Diz-se que um encadeamento possui a fechadura intrínseca entre o momento em que adquiriu a fechadura e liberou a fechadura. Contanto que um thread possua um bloqueio intrínseco, nenhum outro thread pode adquirir o mesmo bloqueio. O outro segmento será bloqueado quando tentar adquirir o bloqueio.

Quando um encadeamento libera um bloqueio intrínseco, um relacionamento acontece antes de ser estabelecido entre essa ação e qualquer aquisição subseqüente do mesmo bloqueio.

Tornar métodos sincronizados tem dois effects :

Primeiro, não é possível que duas invocações de métodos sincronizados no mesmo objeto sejam intercaladas.

Quando um encadeamento está executando um método sincronizado para um objeto, todos os outros encadeamentos que invocam métodos sincronizados para o mesmo bloco de objeto (suspendem execução) até que o primeiro encadeamento seja feito com o objeto.

Segundo, quando um método sincronizado é encerrado, ele estabelece automaticamente um relacionamento acontece antes de qualquer chamada subseqüente de um método sincronizado para o mesmo objeto.

Isso garante que as alterações no estado do objeto sejam visíveis para todos os threads.

Procure outras alternativas para sincronização em:

Evite sincronizado (isso) em Java?

Eu tenho algumas perguntas sobre o uso e importância da palavra synchronized chave synchronized .

  • Qual é o significado da palavra synchronized chave synchronized ?
  • Quando os métodos devem ser synchronized ?
  • O que significa programaticamente e logicamente?

visão global

A palavra-chave sincronizada em Java tem a ver com a segurança do encadeamento, ou seja, quando vários encadeamentos leem ou gravam a mesma variável.
Isso pode acontecer diretamente (acessando a mesma variável) ou indiretamente (usando uma classe que usa outra classe que acessa a mesma variável).

A palavra-chave sincronizada é usada para definir um bloco de código em que vários segmentos podem acessar a mesma variável de maneira segura.

Deeper

Sintaxe-a palavra-chave synchronized leva um Object como seu parâmetro (chamado de objeto de bloqueio ), que é seguido por um { block of code } .

  • Quando a execução encontra essa palavra-chave, o thread atual tenta "bloquear / adquirir / possuir" (escolha) o objeto de bloqueio e executar o bloco de código associado após a aquisição do bloqueio.

  • Quaisquer gravações para variáveis ​​dentro do bloco de código sincronizado são garantidas para serem visíveis para todos os outros threads que executam código similarmente dentro de um bloco de código sincronizado usando o mesmo objeto de bloqueio .

  • Apenas um thread de cada vez pode conter o bloqueio, durante o qual todos os outros threads que tentam adquirir o mesmo objeto de bloqueio aguardarão (pausem sua execução). O bloqueio será liberado quando a execução sair do bloco de código sincronizado.

Métodos Sincronizados:

Adicionar synchronized palavra-chave synchronized a uma definição de método é igual a todo o corpo do método envolvido em um bloco de código sincronizado com o objeto de bloqueio sendo this (por exemplo, métodos) e ClassInQuestion.getClass() (para métodos de classe) .

- O método da instância é um método que não possui static palavra-chave static .
- método de classe é um método que tem palavra-chave static .

Técnico

Sem sincronização, não é garantido em qual ordem as leituras e gravações acontecem, possivelmente deixando a variável com lixo.
(Por exemplo, uma variável pode acabar com metade dos bits escritos por um thread e metade dos bits escritos por outro thread, deixando a variável em um estado que nenhum dos threads tentou escrever, mas uma confusão combinada de ambos.)

Não é suficiente concluir uma operação de gravação em um encadeamento antes (tempo de relógio de parede) de outro encadeamento, porque o hardware poderia ter armazenado em cache o valor da variável, e o encadeamento de leitura veria o valor em cache em vez do que foi gravado isto.

Conclusão

Assim, no caso de Java, você precisa seguir o Modelo de Memória Java para garantir que os erros de encadeamento não aconteçam.
Em outras palavras: use sincronização, operações atômicas ou classes que os usam para você sob os capôs.

Fontes

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Especificação da linguagem Java®, 2015-02-13


A palavra synchronized chave synchronized impede o acesso simultâneo a um bloco de código ou objeto por vários Threads. Por padrão, uma Hashtable é synchronized , portanto, apenas um thread pode acessar a tabela por vez.

No uso de construções non-synchronized como o HashMap , você deve criar recursos de segurança de encadeamento em seu código para evitar erros de consistência de memória.


A palavra-chave synchronized é toda sobre threads diferentes lendo e gravando para as mesmas variáveis, objetos e recursos. Este não é um assunto trivial em Java, mas aqui está uma citação da Sun:

synchronized métodos synchronized permitem uma estratégia simples para evitar interferência de encadeamentos e erros de consistência de memória: se um objeto estiver visível para mais de um encadeamento, todas as leituras ou gravações para as variáveis ​​desse objeto serão feitas por meio de métodos sincronizados.

Em poucas palavras: Quando você tem dois threads que estão lendo e escrevendo para o mesmo 'recurso', digamos uma variável chamada foo , você precisa garantir que esses threads acessem a variável de maneira atômica. Sem a palavra synchronized chave synchronized , seu thread 1 pode não ver o thread de mudança 2 feito para foo , ou pior, ele só pode ser alterado pela metade. Isso não seria o que você espera logicamente.

Novamente, este é um tópico não trivial em Java. Para saber mais, explore os tópicos aqui em SO e nas Interwebs sobre:

Continue explorando esses tópicos até que o nome "Brian Goetz" seja permanentemente associado ao termo "simultaneidade" em seu cérebro.


Bem, eu acho que nós tivemos o suficiente de explicações teóricas, então considere este código

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Nota: O modo synchronized bloqueia a chamada do próximo encadeamento ao método test (), desde que a execução do encadeamento anterior não seja concluída. Threads podem acessar este método um de cada vez. Sem synchronized todos os threads pode acessar esse método simultaneamente.

Quando um encadeamento chama o método sincronizado 'teste' do objeto (aqui o objeto é uma instância da classe 'TheDemo') ele adquire o bloqueio desse objeto, qualquer novo encadeamento não pode chamar QUALQUER método sincronizado do mesmo objeto contanto que o encadeamento anterior que adquiriu o bloqueio não libera a fechadura.

Coisa semelhante acontece quando qualquer método sincronizado estático da classe é chamado. O encadeamento adquire o bloqueio associado à classe (nesse caso, qualquer método sincronizado não estático de uma instância dessa classe pode ser chamado por qualquer encadeamento porque esse bloqueio de nível de objeto ainda está disponível). Qualquer outro segmento não poderá chamar qualquer método sincronizado estático da classe, desde que o bloqueio de nível de classe não seja liberado pelo encadeamento que atualmente mantém o bloqueio.

Saída sincronizada

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Saída sem sincronização

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9

No meu entender, sincronizado basicamente significa que o compilador escreve um monitor.enter e monitor.exite em torno do seu método. Como tal, pode ser thread-safe dependendo de como ele é usado (o que quero dizer é que você pode escrever um objeto com métodos sincronizados que não são threadsafe, dependendo do que sua classe faz).


Pense nisso como uma espécie de catraca como você pode encontrar em um campo de futebol. Existem vapores paralelos de pessoas que querem entrar, mas na catraca são "sincronizadas". Somente uma pessoa por vez pode passar. Todos aqueles que querem passar podem fazer, mas podem ter que esperar até que possam passar.


Sincronizado é uma palavra-chave em Java que é usada para fazer acontecer antes do relacionamento no ambiente multithreading para evitar inconsistência de memória e erro de interferência de encadeamento.


Sincronizado simples significa que não há dois segmentos podem acessar o bloco / método simultaneamente. Quando dizemos que qualquer bloco / método de uma classe é sincronizado, significa que apenas um segmento pode acessá-los de cada vez. Internamente, o encadeamento que tenta acessá-lo primeiro obtém um bloqueio nesse objeto e, enquanto esse bloqueio não estiver disponível, nenhum outro encadeamento poderá acessar qualquer um dos métodos / blocos sincronizados dessa instância da classe.

Observe que outro thread pode acessar um método do mesmo objeto que não está definido para ser sincronizado. Um thread pode liberar o bloqueio chamando

Object.wait()

Synchronized normal method equivalente à Synchronized statement (use isso)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static method equivalente à Synchronized statement (classe de uso)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Instrução sincronizada (usando variável)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

Para synchronized , temos os Synchronized Methods Synchronized Statements e as Synchronized Statements . No entanto, os Synchronized Methods são semelhantes às Synchronized Statements portanto, precisamos entender as Synchronized Statements .

=> Basicamente, nós teremos

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Aqui está 2 acho que ajuda a compreensão synchronized

  • Cada objeto / classe possui um intrinsic lock associado a ele.
  • Quando um encadeamento chama uma synchronized statement , ele automaticamente adquire o intrinsic lock para synchronized statement's objeto dessa synchronized statement's e o libera quando o método retorna. Contanto que um thread possua um intrinsic lock , nenhum outro thread pode adquirir o SAME lock => thread safe.

=> Quando um thread A invoca synchronized(this){// code 1} => todo o código de bloco (dentro da classe) onde synchronized(this) e todo synchronized normal method (dentro da classe) é bloqueado porque SAME lock. Ele será executado após o thread A unlock ("// code 1" terminado).

Esse comportamento é semelhante ao synchronized(a variable){// code 1} ou synchronized(class) .

SAME LOCK => lock (não depende de qual método? Ou quais declarações?)

Use o método sincronizado ou instruções sincronizadas?

Eu prefiro synchronized statements porque é mais extensível. Exemplo, no futuro, você só precisa sincronizar uma parte do método. Exemplo, você tem 2 métodos sincronizados e não tem qualquer relevância um para o outro, no entanto, quando um thread executa um método, ele bloqueia o outro método (ele pode evitar pelo uso synchronized(a variable) ).

No entanto, aplicar o método sincronizado é simples e o código parece simples. Para alguma classe, há apenas 1 método sincronizado, ou todos os métodos sincronizados na classe em relevância um para o outro => podemos usar o synchronized method para tornar o código mais curto e fácil de entender

Nota

(não é relevante muito para synchronized , é o diferente entre objeto e classe ou nenhum estático e estático).

  • Quando você usa o método synchronized ou normal ou synchronized(this) ou synchronized(non-static variable) ele será sincronizado com base em cada instância do objeto.
  • Quando você usa o método synchronized ou estático ou synchronized(class) ou synchronized(static variable) ele será sincronizado com base na classe

Referência

page

Espero que ajude





synchronized