Java多线程 活锁

活性故障

死锁是最常见的活跃性问题, 除了死锁外, 还有类似的问题导致程序无法顺利的执行, 统称为活跃性问题. 例如 活锁 (Livelock) 饥饿

活锁 (Livelock)

什么是活锁
活锁具有两个特点,
第一个是线程没有阻塞, 始终在运行中(所以叫活锁, 线程是活的, 运行中的. )
第二个特点: 程序却得不到进展, 因为线程始终重复同样的无效事情.

如下图 , 两个绅士弯腰, 如果是死锁, 那么就是两个人始终一动不动, 直到对方先抬头, 不再有对话, 只是等待.

如果是活锁, 双方都在不停的与对方说话, 是在运行中的, 在计算机中是消耗系统资源的.

死锁与活锁的结果是一样的, 谁都不能先抬头.

代码演示
可以看如下的这篇文章
https://huadong.blog.csdn.net/article/details/103078399

只有在小于9的情况下, 才会把勺子给对方, 而大部分情况下是小于9的,
random.nextInt(10) 获取的值的范围是0 到9 (包含9). 那么如果获取的是9 , 就不会让给对方, 自己就会先吃.
即百分之90的概率谦让 , 百分之10的概率不谦让.

工程中的活锁实例: 消息队列

工程中的活锁实例: 消息队列
消息队列如果处理失败, 会在catch的地方, 进行重试的策略,
假如把该消息放在队列的头中, 即每次重试的都是该失败的消息, 并且 该消息依赖的服务处了问题, 处理该消息就会一直失败, 那么就造成了活锁. 即没有进入阻塞状态, 但程序无法继续下去 .

解决办法 :

  1. 不把该发送失败的消息放在头中, 而是放入队列的末尾中, 这样即使发送失败了, 也不影响其他消息的发送.
  2. 限制重试的次数, 例如3 次, 5次 , 根据业务的不同设置重试的上限, 如果不限制重试的次数, 会消耗系统资源. 如果达到重试的次数还是没有发送成功后, 放入数据库中,数据库 如果有插入新的发送失败的消息后, 一方面触发报警机制, 另一方面, 把这些发送失败的消息, 有额外的定时任务去执行和重试, 这样就不会影响到主程序的运行.

猜你喜欢

转载自blog.csdn.net/qq_33229669/article/details/108559140
今日推荐