Java 线程活锁怎么理解
java 中的线程活锁是指多个线程因相互响应对方的状态而陷入无限循环,导致没有任何线程能够继续执行的情况。与死锁不同,活锁中的线程通常处于可运行状态(runnable),但由于逻辑上的互相谦让或重试策略不当,它们无法取得实质性的进展。解决活锁的关键在于引入随机性、设置重试上限或改变协作机制。

基于重试机制的活锁场景分析
当多个线程尝试获取同一资源时,如果失败后立刻重试且没有退避策略,就会形成活锁。例如,两个线程 A 和 B 同时尝试获取锁 L,若获取失败则立即释放并重新尝试,由于两者同步失败,它们会不断重复这一过程。

import java.util.concurrent.locks.ReentrantLock;
public class LivelockExample {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
if (lock.tryLock()) {
System.out.println("Thread 1 acquired lock");
try {
// 模拟工作
Thread.sleep(10);
} catch (InterruptedException e) {
break;
} finally {
lock.unlock();
}
break; // 成功则退出
} else {
System.out.println("Thread 1 failed to acquire lock, retrying immediately");
// 无退避,直接重试
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
if (lock.tryLock()) {
System.out.println("Thread 2 acquired lock");
try {
// 模拟工作
Thread.sleep(10);
} catch (InterruptedException e) {
break;
} finally {
lock.unlock();
}
break; // 成功则退出
} else {
System.out.println("Thread 2 failed to acquire lock, retrying immediately");
// 无退避,直接重试
}
}
});
t1.start();
t2.start();
}
}
基于消息队列的活锁场景分析
在分布式系统或消息处理中,活锁常出现在“谦让”逻辑中。例如,两个服务节点收到彼此的消息后,为了表示尊重或避免冲突,主动将消息延迟发送,结果导致消息在两者之间无限传递,永远无法被最终处理。

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class MessageLivelock {
static class Message implements Delayed {
private String content;
private long delayTime;
public Message(String content, long delay) {
this.content = content;
this.delayTime = System.currentTimeMillis() + delay;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Long.compare(this.delayTime, ((Message)o).delayTime);
}
@Override
public String toString() {
return "Message[" + content + "]";
}
}
public static void main(String[] args) {
DelayQueue<message> queue = new DelayQueue();
Thread sender1 = new Thread(() -> {
try {
for (int i = 0; i {
try {
while (true) {
Message msg = queue.take();
if (msg.getContent().equals("From Node 1")) {
// 谦让:不处理,而是重新发送一个延迟更长的消息
Message reply = new Message("Reply from Node 2", 2000);
queue.put(reply);
System.out.println("Node 2 received and deferred processing");
}
}
} catch (InterruptedException e) {}
});
sender1.start();
receiver1.start();
}
}</message>
如何检测和避免线程活锁
检测活锁比检测死锁困难,因为线程并未阻塞。可以通过监控线程的执行进度、记录操作次数或设置超时机制来发现异常。避免活锁的方法包括:引入随机退避时间、限制重试次数、使用优先级调度或改变资源获取顺序。在实际开发中,应优先使用有界重试和指数退避算法,确保系统在极端情况下仍能取得进展。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











