来看Java实际与理论: 构建一个更好的HashMap
你说是sun公司对她研究的透还是微软?针对自己工具开发的.net网页编程性能上肯定会站上风的。ConcurrentHashMap是DougLea的util.concurrent包的一部分,它供应比Hashtable大概synchronizedMap更高水平的并发性。并且,关于年夜多半成功的get()操纵它会想法制止完整锁定,其了局就是使得并发使用程序有着非常好的吞吐量。这个月,BrianGoetz细心剖析了ConcurrentHashMap的代码,并切磋DougLea是怎样在不丧失线程平安的情形下获得这么骄人成就的。
在7月份的那期Java实际与理论(“Concurrentcollectionsclasses”)中,我们复杂地回忆了可伸缩性的瓶颈,并会商了怎样用共享数据布局的办法获得更高的并发性和吞吐量。偶然候进修的最好办法是剖析专家的功效,以是这个月我们将剖析DougLea的util.concurrent包中的ConcurrentHashMap的完成。JSR133将指定ConcurrentHashMap的一个版本,该版本针对Java内存模子(JMM)作了优化,它将包括在JDK1.5的java.util.concurrent包中。util.concurrent中的版本在老的和新的内存模子中都已经由过程线程平安考核。
针对吞吐量举行优化
ConcurrentHashMap利用了几个技能来取得高水平的并发和制止锁定,包括为分歧的hashbucket(桶)利用多个写锁和利用JMM的不断定性来最小化锁被坚持的工夫DD大概基本制止猎取锁。关于年夜多半一样平常用法来讲它是经由优化的,这些用法常常会检索一个极可能在map中已存在的值。现实上,多半乐成的get()操纵基本不必要任何锁定就可以运转。(告诫:不要本人试图如许做!想比JMM伶俐不像看上往的那末简单。util.concurrent类是由并发专家编写的,而且在JMM平安性方面经由了严厉的偕行评审。)
多个写锁
我们能够回忆一下,Hashtable(大概替换计划Collections.synchronizedMap)的可伸缩性的次要停滞是它利用了一个map局限(map-wide)的锁,为了包管拔出、删除大概检索操纵的完全性必需坚持这样一个锁,并且偶然候乃至还要为了包管迭代遍历操纵的完全性坚持如许一个锁。如许一来,只需锁被坚持,就从基本上制止了其他线程会见Map,即便处置器有余暇也不克不及会见,如许年夜年夜地限定了并发性。
ConcurrentHashMap摒弃了单一的map局限的锁,取而代之的是由32个锁构成的汇合,个中每一个锁卖力回护hashbucket的一个子集。锁次要由变更性操作(put()和remove())利用。具有32个自力的锁意味着最多能够有32个线程能够同时修正map。这其实不必定是说在并发地对map举行写操纵的线程数少于32时,别的的写操纵不会被堵塞DD32关于写线程来讲是实际上的并发限定数量,可是实践上大概达不到这个值。可是,32仍然比1要好很多,并且关于运转于今朝这一代的盘算机体系上的年夜多半使用程序来讲已充足了。 
map局限的操纵
有32个自力的锁,个中每一个锁回护hashbucket的一个子集,如许必要独占会见map的操纵就必需取得一切32个锁。一些map局限的操纵,好比说size()和isEmpty(),大概可以不必一次锁全部map(经由过程得当地限制这些操作的语义),可是有些操纵,好比map重排(扩展hashbucket的数目,跟着map的增加从头散布元素),则必需包管独有会见。Java言语不供应用于猎取可变巨细的锁汇合的烦琐办法。必需这么做的情形很少见,一旦碰着这类情形,可以用递回办法来完成。
JMM概述
在进进put()、get()和remove()的完成之前,让我们先复杂地看一下JMM。JMM掌管着一个线程对内存的举措(读和写)影响其他线程对内存的举措的体例。因为利用处置器存放器和预处置cache来进步内存会见速率带来的性能提拔,Java言语标准(JLS)同意一些内存操纵其实不关于一切其他线程当即可见。有两种言语机制可用于包管跨线程内存操纵的分歧性DDsynchronized和volatile。
依照JLS的说法,“在没有显式同步的情形下,一个完成能够自在地更新主存,更新时所接纳的按次多是出人意表的。”其意义是说,假如没有同步的话,在一个给定线程中某种按次的写操纵关于别的一个分歧的线程来讲大概出现出分歧的按次,而且对内存变量的更新从一个线程传布到别的一个线程的工夫是不成展望的。
固然利用同步最多见的缘故原由是包管对代码关头部分的原子会见,但实践上同步供应三个自力的功效DD原子性、可见性温柔序性。原子性十分复杂DD同步实行一个可重进的(reentrant)互斥,避免多于一个的线程同时实行由一个给定的监督器回护的代码块。不幸的是,多半文章都只存眷原子性方面,而疏忽了其他方面。可是同步在JMM中也饰演着很主要的脚色,会引发JVM在取得和释放监督器的时分实行内存壁垒(memorybarrier)。
一个线程在取得一个监督器以后,它实行一个读屏蔽(readbarrier)DD使得缓存在线程部分内存(好比说处置器缓存大概处置器存放器)中的一切变量都生效,如许就会招致处置重视新从主存中读取同步代码块利用的变量。与此类似,在开释监督器时,线程会实行一个写屏蔽(writebarrier)DD将一切修悔改的变量写回主存。互斥独有和内存壁垒分离利用意味着只需您在程序计划的时分遵守准确的同步法例(也就是说,每当写一个前面大概被其他线程会见的变量,大概读取一个大概最初被另外一个线程修正的变量时,都要利用同步),每一个线程城市失掉它所利用的共享变量的准确的值。
假如在会见共享变量的时分没有同步的话,就会产生一些奇异的事变。一些变更大概会经由过程线程当即反应出来,而其他的则必要一些工夫(这由联系关系缓存的实质而至)。了局,假如没有同步您就不克不及包管内存内容一定分歧(相干的变量互相间大概会纷歧致),大概不克不及失掉以后的内存内容(一些值多是过期的)。制止这类伤害情形的经常使用办法(也是保举利用的办法)固然是准确地利用同步。但是在有些情形下,好比说在像ConcurrentHashMap之类的一些利用十分广泛的库类中,在开辟历程傍边还必要一些分外的专业妙技和勉力(大概比一样平常的开辟要多出良多倍)来取得较高的功能。
<p>
在性能方面,在windows平台下,.net网页编程可能是占强项,要是把.net网页编程放在sun开发的操作系统上去运行呢?根本就运行不了,.net网页编程对其它操作系统的支持也很弱,性能也可能比不上java。 Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。 Java 编程语言的风格十分接近C、C++语言。 设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧 所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。 是一种为 Internet发展的计算机语言 一直感觉JAVA很大,很杂,找不到学习方向,前两天在网上找到了这篇文章,感觉不错,给没有方向的我指了一个方向,先不管对不对,做下来再说。 Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站 如果要向java web方向发展也要吧看看《Java web从入门到精通》学完再到《Struts2.0入门到精通》这样你差不多就把代码给学完了。有兴趣可以看一些设计模块和框架的包等等。 J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。 多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。 一直感觉JAVA很大,很杂,找不到学习方向,前两天在网上找到了这篇文章,感觉不错,给没有方向的我指了一个方向,先不管对不对,做下来再说。 所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。 Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)
页:
[1]