由性能优化引起的活锁现象

一、活锁定义(源自百度百科)

活锁指的是任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。 活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;活锁有可能自行解开,死锁则不能。

活锁可以认为是一种特殊的饥饿。 下面这个例子在有的文章里面认为是活锁。实际上这只是一种饥饿。因为没有体现出“活”的特点。 假设事务T2再不断的重复尝试获取锁R,那么这个就是活锁。
如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放了R上的封锁后,系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放了R上的封锁之后,系统又批准了T4的请求......T2可能永远等待。

活锁应该是一系列进程在轮询地等待某个不可能为真的条件为真。活锁的时候进程是不会blocked,这会导致耗尽CPU资源。

二、活锁的例子

1、单一实体的活锁
例如线程从队列中拿出一个任务来执行,如果任务执行失败,那么将任务重新加入队列,继续执行。假设任务总是执行失败,或者某种依赖的条件总是不满足,那么线程一直在繁忙却没有任何结果。
2、协同导致的活锁
生活中的典型例子: 两个人在窄路相遇,同时向一个方向避让,然后又向另一个方向避让,如此反复。
通信中也有类似的例子,多个用户共享信道(最简单的例子是大家都用对讲机),同一时刻只能有一方发送信息。发送信号的用户会进行冲突检测, 如果发生冲突,就选择避让,然后再发送。 假设避让算法不合理,就导致每次发送,都冲突,避让后再发送,还是冲突。
计算机中的例子:两个线程发生了某些条件的碰撞后重新执行,那么如果再次尝试后依然发生了碰撞,长此下去就有可能发生活锁。

三、示例说明((下述的例子不一定就要去优化,只是直觉上的一种冲动))

类 Test 变量声明:

private static short counter = (short) 0;
方法定义:
protected static short getCount() {
synchronized(Test.class) {
if (counter<0) counter=0;
return counter++;
}
}
看到上述写法,就有优化的冲动:

private static AtomicInteger counter = new AtomicInteger();

protected static short getCount() {
int i = counter.getAndIncrement();
while (i >= Short.MAX_VALUE) {
counter.compareAndSet(i, 0);//------------------------------CAS指令1
i = counter.getAndIncrement();//-----------------------------CAS指令2
}
return (short)i;
}
并发测试,在某种情况下出现了错误,直到 i 成为了一个负数,也完全违背了这个方法设计的初衷。---------------返回一个非负Short值。
指令1 和指令2 在不同的线程间切换调用。出现活锁现象(虽然最终退出程序,却得到一个错误的结果。)

四、活锁的解决方法

1、解决协同活锁的一种方案是调整重试机制。
比如引入一些随机性。例如如果检测到冲突,那么就暂停随机的一定时间进行重试。这回大大减少碰撞的可能性。
 典型的例子是以太网的CSMA/CD检测机制。
2、另外为了避免可能的死锁,适当加入一定的重试次数也是有效的解决办法。
尽管这在业务上会引起一些复杂的逻辑处理。
比如约定重试机制避免再次冲突。 例如自动驾驶的防碰撞系统(假想的例子),可以根据序列号约定检测到相撞风险时,序列号小的飞机朝上飞, 序列号大的飞机朝下飞。

五、一些启示

性能优化有风险,测试需谨慎。多线程编程中,最容易注重的地方就是避免产生死锁现象,而对于线程饥饿或是活锁现象一般较少顾及。需要引起足够的重视才行。
在确实有证据证明存在性能瓶颈的地方,优化以后完整,完善的测试必不可少。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值