Como uma ferramenta para compartilhar dados simultaneamente e garantir consistência, os bloqueios têm múltiplas implementações na plataforma JAVA (como sincronizado e ReentrantLock, etc.). Esses bloqueios já escritos proporcionam comodidade para o nosso desenvolvimento, mas a natureza específica e o tipo dos bloqueios raramente são mencionados. Esta série de artigos analisará nomes e características comuns de bloqueios em JAVA para responder às suas perguntas.
4. Bloqueio reentrante:
Este artigo fala sobre bloqueios reentrantes em um sentido amplo, não apenas sobre ReentrantLock em JAVA.
Bloqueios reentrantes, também chamados de bloqueios recursivos, significam que após a função externa do mesmo thread adquirir o bloqueio, a função recursiva interna ainda possui o código para adquirir o bloqueio, mas não é afetado.
No ambiente JAVA, ReentrantLock e sincronizado são bloqueios reentrantes.
Aqui estão exemplos de uso:
Copie o código do código da seguinte forma:
classe pública Teste implementa Runnable{
público sincronizado void get(){
System.out.println(Thread.currentThread().getId());
definir();
}
conjunto de void sincronizado público(){
System.out.println(Thread.currentThread().getId());
}
@Substituir
execução void pública() {
pegar();
}
public static void main(String[] args) {
Teste ss=new Teste();
novo Thread(ss).start();
novo Thread(ss).start();
novo Thread(ss).start();
}
}
Os resultados finais de ambos os exemplos estão corretos, ou seja, o mesmo ID de thread é gerado duas vezes consecutivas.
O resultado é o seguinte:
Copie o código do código da seguinte forma:
Tópico: 8
Tópico: 8
Tópico: 10
Tópico: 10
Tópico: 9
Tópico: 9
A maior função dos bloqueios reentrantes é evitar impasses.
Vamos pegar o spin lock como exemplo.
Copie o código do código da seguinte forma:
classe pública SpinLock {
private AtomicReference<Thread> proprietário =new AtomicReference<>();
bloqueio de vazio público(){
Tópico atual = Thread.currentThread();
while(!owner.compareAndSet(null, atual)){
}
}
desbloqueio público vazio (){
Tópico atual = Thread.currentThread();
proprietário.compareAndSet (atual, nulo);
}
}
Para bloqueios giratórios:
1. Se o mesmo thread chamar lock() duas vezes, fará com que a posição do bloqueio seja chamada pela segunda vez. Se ocorrer um deadlock, significa que o bloqueio não é reentrante. (Na função de bloqueio, você deve verificar se o thread é o thread que obteve o bloqueio)
2. Se o problema 1 tiver sido resolvido, o bloqueio terá sido liberado quando unlock() for chamado pela primeira vez. O bloqueio não deve realmente ser liberado.
(Usando tempos de contagem para estatísticas)
Após a modificação, fica da seguinte forma:
Copie o código do código da seguinte forma:
classe pública SpinLock1 {
private AtomicReference<Thread> proprietário =new AtomicReference<>();
contagem interna privada =0;
bloqueio de vazio público(){
Tópico atual = Thread.currentThread();
if(atual==proprietário.get()) {
contar++;
retornar ;
}
while(!owner.compareAndSet(null, atual)){
}
}
desbloqueio público vazio (){
Tópico atual = Thread.currentThread();
if(atual==proprietário.get()){
if(contagem!=0){
contar--;
}outro{
proprietário.compareAndSet (atual, nulo);
}
}
}
}
Este bloqueio de rotação é um bloqueio reentrante.