前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Unsafe实现“无锁”的原子数据结构 | 锁系列-Java中的锁

使用Unsafe实现“无锁”的原子数据结构 | 锁系列-Java中的锁

作者头像
ImportSource
发布2018-04-03 12:05:50
8520
发布2018-04-03 12:05:50
举报
文章被收录于专栏:ImportSourceImportSource

现在市面上很少有关于Unsafe的话题。这个Unsafe有个compareAndSwap方法是原子的,并且使用这个方法可以实现高性能的lock-free的数据结构。

现在我们假设一个场景,多个线程试图同时访问计数器:

首先我们定义一个计数器的接口:

然后我们定义一个工作线程 CounterClient ,里边使用我们传入的具体实现的Counter:

测试demo代码:

首先我们实现一个没有同步的计数器:

输出:

速度倒是挺快的,但是线程之间完全没有排队,所以自然结果是不正确的。

接下来我们通过添加synchronized关键字来实现简答的计数器:

输出:

返回结果是正确的。但是速度明显下降了。接下来我们尝试使用ReentrantReadWriteLock:

输出:

结果依然是没问题的, 而且性能看起来要好了一点。 如果我们使用原子类型呢?接下来看看吧:

输出:

使用原子类型,结果自然是正确的,而且性能貌似看起来更好了

最后,我们尝试使用Unsafe这个底层的类中的compareAndSwapLong,也就是CAS来看看效果:

输出:

结果自然是正确的。其实原子类型的内部实现就是使用Unsafe的CAS。

事实上,这个例子非常的简单,但它却展示了Unsafe的力量和神奇之处。

就像我们前面说到的那样,CAS原子操作可以被用作实现“无锁”的数据结构。

背后的原理很简单:

1、 拥有一个状态

2、复制一份这个状态

3、然后修改它

4、然后执行CAS

5、如果失败则重试

当然了,实际上远比我们想像的要难得多。 有很多问题,如ABA问题,指令重新排序等。

另外其实也可以尝试在counter添加volatile关键字来避免死锁。

另外就是Unsafe这个类,我们普通的开发并不能轻易的访问到。上面的代码中使用到了反射来搞定,所以性能会有一些损耗。

Java是一个安全的开发工具,它阻止开发人员犯很多低级的错误,而大部份的错误都是基于内存管理方面的。如果你想搞破坏,可以使用Unsafe这个类。这个类是属于sun.* API中的类,并且它不是J2SE中真正的一部份,因此你可能找不到任何的官方文档,更可悲的是,它也没有比较好的代码文档。

而且据说在Java9以后,这个类会被彻底隐藏掉,这个类也是蛮心酸的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档