你的位置:首页 > 软件开发 > Java > 无锁编程:采用不可变类减少锁的使用

无锁编程:采用不可变类减少锁的使用

发布时间:2016-06-11 17:00:03
很多的同学很少使用、或者干脆不了解不可变类(Immutable Class)。直观上很容易认为Immutable类效率不高,或者难以理解他的使用场景。其实不可变类是非常有用的,可以提高并行编程的效率和优化设计。让我们跳过一些宽泛的介绍,从一个常见的并行编程场景说起: 假设 ...

 

很多的同学很少使用、或者干脆不了解不可变类(Immutable Class)。直观上很容易认为Immutable类效率不高,或者难以理解他的使用场景。其实不可变类是非常有用的,可以提高并行编程的效率和优化设计。让我们跳过一些宽泛的介绍,从一个常见的并行编程场景说起:

 

假设系统需要实时地处理大量的订单,这些订单的处理依赖于用户的配置,例如用户的会员级别、支付方式等。程序需要通过这些配置的参数来计算订单的价格。而用户配置同时被另外一些线程更新。显然,我们在订单计算的过程中保持配置的一致性。

 

上面的例子是我虚拟出来的,但是类似的场景非常常见--线程A实时地大量地处理请求;线程B偶尔地修改线程A依赖的配置信息。我们陷入这样的两难:

1,为了保持配置的一致性,我们不得不在线程A和线程B上,对配置的读和写都加锁,才能保障配置的一致性。这样才能保证请求处理过程中,不会出现某些配置项被更新了,而另外一些没有;或者处理中开始使用的是旧配置,而后又使用新的配置。(听起来类似于数据库的脏读问题)

2,另一方面,线程A明显比线程B更繁忙,为了偶尔一次的配置更新,为每秒数以万次的请求处理加锁,显然代价太高了。

 

解决方案

解决方案有两种:

第一种是,采用ReadWriteLock。这是最常见的方式。

对读操作加读锁,对写操作加写锁。如果没有正在发生的写操作,读锁的代价很低。

 

第二种是,采用不可变对象来保存配置信息,用替换配置对象的方式,而不是修改配置对象的方式,来更新配置信息。让我们来思考一下这么做的利弊:

1)对于订单处理线程A来说,它不再需要加锁了!因为用于保存配置的对象是不可变对象。我们要么读取的是一个旧的配置对象,要么是一个新的配置对象(新的配置对象覆盖了旧的配置对象)。不会出现“脏读”的情况。

2)对于用于更新配置的线程B,它的负担加重了 -- 更新任何一项配置,都必须重新创建一个新的不可变对象,然后把更新的新的属性和其他旧属性赋给新的对象,最后覆盖旧的对象,被抛弃的旧对象还增加了GC的负担。而原本,这一切只要一个set操作就能完成。

 

我们如何衡量利弊呢?经常,这是非常划算的,线程A和线程B的工作量可能相差几个数量级。用线程B压力的增加(其实不值一提)来换取线程A可以不用锁,效率应该会有很大提升。

 

代码及性能测试

让我们用代码来测试一下哪个解决方案更好。

 

方案一:采用ReentrantReadWriteLock来加读写锁:

一个普通的配置类,保存了用户的优惠信息,包括会员优惠和特殊节日优惠,在计算订单总价的时候用到:

public class AccountConfig {  private double membershipDiscount;  private double specialEventDiscount;    public AccountConfig(double membershipDiscount, double specialEventDiscount)  {    this.membershipDiscount = membershipDiscount;    this.specialEventDiscount = specialEventDiscount;  }  public double getMembershipDiscount() {    return membershipDiscount;  }  public void setMembershipDiscount(double membershipDiscount) {    this.membershipDiscount = membershipDiscount;  }  public double getSpecialEventDiscount() {    return specialEventDiscount;  }  public void setSpecialEventDiscount(double specialEventDiscount) {    this.specialEventDiscount = specialEventDiscount;  }}


 

海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

原标题:无锁编程:采用不可变类减少锁的使用

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录