A livelock is similar to a deadlock, but with a twist:
Threads keep changing their state in response to each other, but make no real progress.
They’re not blocked (like in a deadlock), but they’re too polite — constantly reacting to each other, leading to an endless loop of “after you, no, after you…”
🧠 Deadlock vs. Livelock
Aspect | Deadlock | Livelock |
---|---|---|
Threads state | Blocked (waiting for a lock) | Active (running, retrying) |
Progress | None | None |
Cause | Circular wait | Constant mutual reactions |
Looks like | Freeze | Endless spinning without progress |
🔄 Livelock Analogy
Two people meet in a hallway:
- Person A steps to the left to let B pass.
- Person B also steps to the left.
- Then both step to the right. Still blocked.
- They keep stepping back and forth — forever.
class Spoon {
private Diner owner;
public Spoon(Diner d) {
this.owner = d;
}
public synchronized void use() {
System.out.println(owner.name + " is eating with the spoon.");
}
public Diner getOwner() {
return owner;
}
public void setOwner(Diner d) {
this.owner = d;
}
}
class Diner {
public String name;
public boolean isHungry = true;
public Diner(String name) {
this.name = name;
}
public void eatWith(Spoon spoon, Diner spouse) {
while (isHungry) {
// Check if it's this diner’s turn
if (spoon.getOwner() != this) {
try { Thread.sleep(1); } catch (InterruptedException ignored) {}
continue;
}
// Be polite: wait for spouse
if (spouse.isHungry) {
System.out.println(name + ": You eat first my dear " + spouse.name);
spoon.setOwner(spouse);
continue;
}
// Eat!
spoon.use();
isHungry = false;
System.out.println(name + ": I'm done eating.");
spoon.setOwner(spouse);
}
}
}
public class LivelockExample {
public static void main(String[] args) {
final Diner husband = new Diner("Husband");
final Diner wife = new Diner("Wife");
final Spoon spoon = new Spoon(husband);
new Thread(() -> husband.eatWith(spoon, wife)).start();
new Thread(() -> wife.eatWith(spoon, husband)).start();
}
}
💡 What’s Happening?
- Both threads run.
- Each sees the other is hungry and gives up the spoon.
- Neither eats.
- They keep passing the spoon back and forth — forever.
→ That’s livelock.
✅ How to Avoid Livelock
- Use backoff algorithms (e.g., random delay before retrying).
- Add timeout conditions or a maximum retry limit.
- Don’t design overly “polite” behavior — be assertive with shared resources.