java.util.concurrent
A API fornece uma classe chamada como Lock
, que basicamente serializaria o controle para acessar o recurso crítico. Dá um método como park()
e unpark()
.
Podemos fazer coisas semelhantes se pudermos usar synchronized
palavras-chave wait()
e notify() notifyAll()
métodos e .
Gostaria de saber qual deles é melhor na prática e por quê?
Respostas:
Se você está simplesmente bloqueando um objeto, eu prefiro usar
synchronized
Exemplo:
Você tem que fazer explicitamente em
try{} finally{}
qualquer lugar.Enquanto que com o sincronizado, é super claro e impossível errar:
Dito isto,
Lock
s pode ser mais útil para coisas mais complicadas, nas quais você não pode adquirir e liberar de maneira tão limpa. Sinceramente, prefiro evitar o uso de bareLock
s em primeiro lugar e optar por um controle de concorrência mais sofisticado, como aCyclicBarrier
ou aLinkedBlockingQueue
, caso atendam às suas necessidades.Eu nunca tive um motivo para usar
wait()
ou,notify()
mas pode haver alguns bons.fonte
std::lock_guard
Descobri que
Lock
eCondition
(e outras novasconcurrent
classes) são apenas mais ferramentas para a caixa de ferramentas. Eu pude fazer quase tudo o que precisava com meu martelo de garra antigo (asynchronized
palavra - chave), mas era difícil de usar em algumas situações. Várias dessas situações embaraçosas se tornaram muito mais simples quando adicionei mais ferramentas à minha caixa de ferramentas: um martelo de borracha, um martelo de bola, um pé de cabra e alguns socos nas unhas. No entanto , meu antigo martelo de garra ainda vê sua parte no uso.Eu não acho que um seja realmente "melhor" que o outro, mas cada um é mais adequado para diferentes problemas. Em poucas palavras, o modelo simples e a natureza orientada ao escopo
synchronized
ajudam a me proteger de bugs no meu código, mas essas mesmas vantagens às vezes são obstáculos em cenários mais complexos. São esses cenários mais complexos que o pacote simultâneo foi criado para ajudar a resolver. Mas o uso dessas construções de nível superior requer um gerenciamento mais explícito e cuidadoso no código.===
Eu acho que o JavaDoc faz um bom trabalho ao descrever a distinção entre
Lock
esynchronized
(a ênfase é minha):fonte
Você pode obter tudo o que os utilitários em java.util.concurrent fazem com as primitivas de baixo nível
synchronized
, comovolatile
, ou aguardar / notificarNo entanto, a simultaneidade é complicada e a maioria das pessoas erra pelo menos algumas partes, tornando seu código incorreto ou ineficiente (ou ambos).
A API simultânea fornece uma abordagem de nível superior, que é mais fácil (e, como tal, mais segura) de usar. Em poucas palavras, você não precisa
synchronized, volatile, wait, notify
mais usar diretamente.O bloqueio classe em si é no lado de nível inferior desta caixa de ferramentas, você pode nem precisar usar que direta ou (você pode usar
Queues
e Semaphore e outras coisas, etc, na maioria das vezes).fonte
java.util.concurrent
é mais fácil [em geral] do que os recursos de idioma (synchronized
, etc ...). Quando você usa,java.util.concurrent
você tem o hábito de preencherlock.lock(); try { ... } finally { lock.unlock() }
antes de escrever o código, enquanto que com umsynchronized
você está basicamente bem desde o início. Apenas com base nisso, eu diria quesynchronized
é mais fácil (dado que você deseja o seu comportamento) do quejava.util.concurrent.locks.Lock
. par 4Existem 4 fatores principais para você usar
synchronized
oujava.util.concurrent.Lock
.Nota: Bloqueio sincronizado é o que quero dizer quando digo bloqueio intrínseco.
Quando o Java 5 saiu com o ReentrantLocks, eles provaram ter uma diferença notável na taxa de transferência do que no bloqueio intrínseco. Se você estiver procurando por um mecanismo de bloqueio mais rápido e estiver executando a versão 1.5, considere jucReentrantLock. O bloqueio intrínseco do Java 6 agora é comparável.
O jucLock possui diferentes mecanismos de bloqueio. Bloquear interruptível - tente travar até que a rosca de bloqueio seja interrompida; bloqueio temporizado - tente bloquear por um certo período de tempo e desista se não tiver êxito; tryLock - tente bloquear, se algum outro segmento estiver segurando a trava. Isso tudo está incluído além do bloqueio simples. O bloqueio intrínseco oferece apenas bloqueio simples
fonte
Gostaria de acrescentar mais algumas coisas em cima da resposta de Bert F.
Locks
Oferece suporte a vários métodos para controle de bloqueio de granulação mais fina, que são mais expressivos que monitores implícitos (synchronized
bloqueios)Vantagens do bloqueio sobre sincronização na página de documentação
O uso de métodos ou instruções sincronizados fornece acesso ao bloqueio implícito do monitor associado a cada objeto, mas força toda a aquisição e liberação de bloqueio a ocorrer de maneira estruturada em bloco
As implementações de bloqueio fornecem funcionalidade adicional sobre o uso de métodos e instruções sincronizados, fornecendo uma tentativa sem bloqueio de adquirir um
lock (tryLock())
, uma tentativa de adquirir o bloqueio que pode ser interrompido (lockInterruptibly()
e uma tentativa de adquirir o bloqueio que podetimeout (tryLock(long, TimeUnit))
.Uma classe Lock também pode fornecer um comportamento e semântica bastante diferente do bloqueio implícito do monitor, como pedidos garantidos, uso não reentrante ou detecção de deadlock
ReentrantLock : em termos simples, de acordo com meu entendimento,
ReentrantLock
permite que um objeto entre novamente de uma seção crítica para outra seção crítica. Como você já tem bloqueio para inserir uma seção crítica, você pode outra seção crítica no mesmo objeto usando o bloqueio atual.ReentrantLock
principais recursos conforme este artigoVocê pode usar
ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
para adquirir ainda mais controle sobre o bloqueio granular nas operações de leitura e gravação.Além desses três ReentrantLocks, o java 8 fornece mais um bloqueio
Carimbo:
Você pode usar esses carimbos para liberar uma trava ou para verificar se a trava ainda é válida. Os bloqueios carimbados adicionalmente oferecem suporte a outro modo de bloqueio chamado bloqueio otimista.
Dê uma olhada neste artigo sobre o uso de diferentes tipos de
ReentrantLock
eStampedLock
fechaduras.fonte
A principal diferença é a justiça, em outras palavras, os pedidos são tratados como FIFO ou pode haver barcaças? A sincronização no nível do método garante uma alocação justa ou FIFO do bloqueio. Usando
ou
não garante justiça.
Se você tiver muita disputa pelo bloqueio, poderá encontrar facilmente trocas, onde os pedidos mais recentes obtêm o bloqueio e os pedidos mais antigos ficam bloqueados. Vi casos em que 200 threads chegam em pouco tempo para um bloqueio e o segundo chega foi processado por último. Isso é bom para algumas aplicações, mas para outras é mortal.
Consulte o livro "Concorrência Java na prática" de Brian Goetz, seção 13.3 para uma discussão completa sobre este tópico.
fonte
O livro "Java Concurrency In Practice" de Brian Goetz, seção 13.3: "... Como o ReentrantLock padrão, o bloqueio intrínseco não oferece garantias determinísticas de justiça, mas as garantias estatísticas estatísticas da maioria das implementações de bloqueio são boas o suficiente para quase todas as situações ..."
fonte
O bloqueio facilita a vida dos programadores. Aqui estão algumas situações que podem ser alcançadas facilmente com o bloqueio.
Enquanto, o bloqueio e as condições se baseiam no mecanismo sincronizado. Portanto, certamente pode conseguir a mesma funcionalidade que você pode obter usando o bloqueio. No entanto, resolver cenários complexos com o sincronizado pode dificultar sua vida e desviar você da solução do problema real.
fonte
Diferença principal entre bloqueio e sincronizado:
fonte
Bloquear e sincronizar blocos serve ao mesmo propósito, mas depende do uso. Considere a parte abaixo
No caso acima, se um segmento entrar no bloco de sincronização, o outro bloco também estará bloqueado. Se houver vários desses blocos de sincronização no mesmo objeto, todos os blocos serão bloqueados. Nessas situações, o java.util.concurrent.Lock pode ser usado para impedir o bloqueio indesejado de blocos
fonte