现在市面上很少有关于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以后,这个类会被彻底隐藏掉,这个类也是蛮心酸的。
本文分享自 ImportSource 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!