欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

剖析Disruptor:为什么会这么快?(一)锁的缺点(1)

来源: javaer 分享于  点击 17779 次 点评:212

剖析Disruptor:为什么会这么快?(一)锁的缺点(1)


artin Fowler写了一篇非常好的文章,里面不仅提到了Disruptor,而且还解释了Disruptor 如何应用在LMAX的架构里。里面有提及了一些目前没有涉及的概念,但最经常问到的问题是 “Disruptor究竟是什么?"。

目前我正准备在回答这个问题,但首先回答"为什么它会这么快?"

这些问题持续出现,但是我不能没有说它是干什么的就说它为什么会这么快,不能没有说它为什么这样做就说它是什么东西。

所以我陷入了一个僵局,一个如何写博客的僵局。

要打破这个僵局,我准备以最简单方式回答第一个问题,如果幸运的话,在以后博文里,如果需要解释的话我会重新提回:Disruptor提供了一种线程之间信息交换的方式。

作为一个开发者,因为"线程"一词的出现,我的警钟已经敲响,它意味着并发,而并发是困难的。

并发 01

想象有两个线程尝试修改同一个变量value:

情况一:线程1先到达

情况二:线程2先到达

情况三:线程1与线程2交互

情况三显然是唯一一个是错误的,除非除非你认为wiki编辑的幼稚做法是正确的Google Code Wiki,我一直在关注你)。其他两种情况主要是看你的意图和想要达到的效果。线程2可能不会关心变量value的值是什么,主要的意图就是在后面加上字符 ‘y'而不管它原来的值是什么,在这种前提下,情况一和情况二都是正确的。

但是如果线程2只是想把"fluff"改为”fluffy”,那么情况二和三都不正确。假定线程2想把值设为”fluffy”,有几种办法可以解决这个问题:

办法一:悲观锁

(“No Entry”的标志对于在没有在英国开车的人看得明白不?)

悲观锁和乐观锁这两个词通常在我们谈论数据库读写时经常会用到,但原理可以应用到在获得一个对象的锁的情况。

只要线程2一获得Entry 的互斥锁,它就会阻击其它线程去改变它,然后它就可以随意做它要做的事情,设置值,然后做其它事情。

你可以想象这里非常耗性能的,因为其它线程在系统各处徘徊着准备要获得锁然后又阻塞。线程越多,系统的响应性就会越慢.

办法二:乐观锁

在这种情况,当线程2需要去写Entry时才会去锁定它.它需要检查Entry自从上次读过后是否已经被改过了。如果线程1在线程2读完后到达并把值改为”blah”,线程2读到了这个新值,线程2不会把"fluffy"写到Entry里并把线程1所写的数据覆盖.线程2会重试重新读新的值,与旧值比较,如果相等则在变量的值后面附上’y’),这里在线程2不会关心新的值是什么的情况.或者线程2会抛出一个异常,或者会返回一个某些字段已更新的标志,这是在期望把”fluff”改为”fluffy”的情况.举一个第二种情况的例子,如果你和另外一个用户同时更新一个Wiki的页面,你会告诉另外一个用户的线程 Thread 2,它们需要重新加载从Thread1来新的变化,然后再提交它们的内容。

潜在的问题:死锁

锁定会带来各种各样的问题,比如死锁,想象有2个线程需要访问两个资源

如果你滥用锁技术,两个锁都在获得锁的情况下尝试去获得另外一个锁,那就是你应该重启你的电脑的时候了。校注:作者还挺幽默)

很明确的一个问题:锁技术是慢的..

关于锁就是它们需要操作系统去做裁定。线程就像两姐妹在为一个玩具在争吵,然后操作系统就是能决定他们谁能拿到玩具的父母,就像当你跑向你父亲告诉他你的姐姐在你玩着的时候抢走了你的变形金刚-他还有比你们争吵更大的事情去担心,他或许在解决你们争吵之前要启动洗碗机并把它摆在洗衣房里。如果你把你的注意力放在锁上,不仅要花时间来让操作系统来裁定。Disruptor论文中讲述了我们所做的一个实验。这个测试程序调用了一个函数,该函数会对一个 64位的计数器循环自增5亿次。当单线程无锁时,程序耗时300ms。如果增加一个锁仍是单线程、没有竞争、仅仅增加锁),程序需要耗时 10000ms,慢了两个数量级。更令人吃惊的是,如果增加一个线程简单从逻辑上想,应该比单线程加锁快一倍),耗时224000ms。使用两个线程对计数器自增5亿次比使用无锁单线程慢1000倍。并发很难而锁的性能糟糕。我仅仅是揭示了问题的表面,而且,这个例子很简单。但重点是,如果代码在多线程环境中执行,作为开发者将会遇到更多的困难:

  • 代码没有按设想的顺序执行。上面的场景3表明,如果没有注意到多线程访问和写入相同的数据,事情可能会很糟糕。
  • 减慢系统的速度。场景3中,使用锁保护代码可能导致诸如死锁或者效率问题。

这就是为什么许多公司在面试时会多少问些并发问题当然针对Java面试)。不幸的是,即使未能理解问题的本质或没有问题的解决方案,也很容易学会如何回答这些问题。


相关栏目:

用户点评