Um exemplo em que posso pensar é o cenário Mesa, Lanterna e Baterias. Imagine uma lanterna e um par de baterias colocados em cima de uma mesa. Se você fosse até esta mesa e pegasse as baterias enquanto outra pessoa está com a lanterna, vocês dois seriam forçados a se olharem sem jeito enquanto esperam por quem colocará seu item de volta na mesa. Este é um exemplo de impasse. Você e a pessoa estão esperando por recursos, mas nenhum de vocês está desistindo de seus recursos.
Da mesma forma, em um programa, o deadlock ocorre quando dois ou mais threads (você e a outra pessoa) estão esperando que duas ou mais travas (lanterna e baterias) sejam liberadas e as circunstâncias no programa são tais que as travas nunca são liberadas ( vocês dois têm uma peça do quebra-cabeça).
Se você conhece java, é assim que pode representar esse problema:
import java.util.concurrent.locks.*;
public class Deadlock1 {
public static class Table {
private static Lock Flashlight = new ReentrantLock();
private static Lock Batteries = new ReentrantLock();
public static void giveFlashLightAndBatteries() {
try {
Flashlight.lock();
Batteries.lock();
System.out.println("Lights on");
} finally {
Batteries.unlock();
Flashlight.unlock();
}
}
public static void giveBatteriesAndFlashLight() {
try {
Batteries.lock();
Flashlight.lock();
System.out.println("Lights on");
} finally {
Flashlight.unlock();
Batteries.unlock();
}
}
}
public static void main(String[] args) {
// This thread represents person one
new Thread(new Runnable() {
public void run() { Table.giveFlashLightAndBatteries(); }
}).start();
// This thread represents person two
new Thread(new Runnable() {
public void run() { Table.giveBatteriesAndFlashLight(); }
}).start();
}
}
Se você executar este exemplo, notará que às vezes as coisas funcionam bem e corretamente. Mas às vezes seu programa simplesmente não imprime nada. Isso porque uma pessoa está com as pilhas e outra com a lanterna, o que impede que acendam a lanterna causando um travamento.
Este exemplo é semelhante ao exemplo dado pelos tutoriais java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Outro exemplo é o exemplo de loop:
public class Deadlock2 {
public static class Loop {
private static boolean done = false;
public static synchronized void startLoop() throws InterruptedException {
while(!done) {
Thread.sleep(1000);
System.out.println("Not done");
}
}
public static synchronized void stopLoop() {
done = true;
}
}
public static void main(String[] args) {
// This thread starts the loop
new Thread(new Runnable() {
public void run() {
try {
Loop.startLoop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// This thread stops the loop
new Thread(new Runnable() {
public void run() {
Loop.stopLoop();
}
}).start();
}
}
Este exemplo pode imprimir 'Não feito' repetidamente ou nunca pode imprimir 'Não feito'. O primeiro acontece porque o primeiro thread adquire o bloqueio de classe e nunca o libera, evitando que 'stopLoop' seja acessado pelo segundo thread. E o mais recente acontece porque o segundo encadeamento foi iniciado antes do primeiro encadeamento, fazendo com que a variável 'concluído' fosse verdadeira antes de o primeiro encadeamento ser executado.