论坛首页 招聘求职论坛

一个面试官对面试问题的分析

浏览 34278 次
该帖已经被评为良好帖
作者 正文
   发表时间:2010-07-20  
IcyFenix 写道
nomoney 写道
楼主也不过是在考察一个人阅读能力而已.搞java的,但凡喜欢阅读的技术书的人,对楼主提的问题应该都有印像,运气好点儿的,最近刚看还记得.运气差点儿的.早忘了.
我倒是想知道,楼主您不是开发虚拟机的.这问题您就真在工作中被用到了?


我不开发虚拟机,但是这个问题的知识在实际工作中用到很奇怪吗?


您既然不回答,我就当您是没用过了.当然您如果非要编几个例子,我觉得也不是很困难.
0 请登录后投票
   发表时间:2010-07-20  
推荐2篇毒物:
http://cshbbrain.iteye.com/blog/526356
http://cshbbrain.iteye.com/blog/551085
有兴趣的可以多交流。
0 请登录后投票
   发表时间:2010-07-20  
对于Web开发较多的JAVA程序员来霁,JVM之类的知识是点偏

楼主出问题的思维方式,基本上和我国教育体制的考试出题思路高度吻合

主要是能过问些较偏的知识,来看人的能力和知识广度,想起了上学时做那些钻牛角尖的破数学题

我不否认了解了JVM这些知识,对JAVA的认识有了一个新的高度!但人的精力是有限的

就像上学做那些破题是为了分数,学习JVM这种知识最大的用处就是为了面试,如果面试时可以说出这些知识就会让面试官感觉不错

该死,看来为了好工作,还是要把这些偏门的知识看看
0 请登录后投票
   发表时间:2010-07-20   最后修改:2010-07-20
blackstreet 写道
对于Web开发较多的JAVA程序员来霁,JVM之类的知识是点偏

楼主出问题的思维方式,基本上和我国教育体制的考试出题思路高度吻合

主要是能过问些较偏的知识,来看人的能力和知识广度,想起了上学时做那些钻牛角尖的破数学题

我不否认了解了JVM这些知识,对JAVA的认识有了一个新的高度!但人的精力是有限的

就像上学做那些破题是为了分数,学习JVM这种知识最大的用处就是为了面试,如果面试时可以说出这些知识就会让面试官感觉不错

该死,看来为了好工作,还是要把这些偏门的知识看看


这个帖子中有同学出了一组数据库相关的题目,我超过一半不会做,在自己出了题的帖子被别人题目打击,很没面子:(,但是我觉得自己没有办法把“不会回答”的责任推至对方出的题目,或者这些题目涉及的知识上太偏上,只能说我学习工作中没有接触到,或者使用过了但是没有注意总结形成自己的思想。而顶楼我发的题目与观点,大多是自己学习、使用的总结,并且以后工作上还需要经常用到的知识,所以我拿来发问,知识点偏与不偏,只是似乎人与角度而已。

每个人都有自己的观点,如果你觉得“对JAVA的认识有了一个新的高度!但人的精力是有限的,学习JVM这种知识最大的用处就是为了面试”,我可以认同这是你与不小的一部分开发者的想法,我不会这样想但也不会对这种想法表示不屑。我自己的看法是如果哪天我觉得“精力有限”,觉得接受新知识是种负担而不是一种乐趣,那可能我就该准备转管理方向了。

最后在帮知识二字喊一声冤枉:我国可能教育制度确实有很大偏颇,但只是培养和考察方式的责任,“恨屋及乌”的把各种知识没有道理,没有绝对无用的偏门知识,只有你不使用的知识。
1 请登录后投票
   发表时间:2010-07-21  
IcyFenix 写道
blackstreet 写道
对于Web开发较多的JAVA程序员来霁,JVM之类的知识是点偏

楼主出问题的思维方式,基本上和我国教育体制的考试出题思路高度吻合

主要是能过问些较偏的知识,来看人的能力和知识广度,想起了上学时做那些钻牛角尖的破数学题

我不否认了解了JVM这些知识,对JAVA的认识有了一个新的高度!但人的精力是有限的

就像上学做那些破题是为了分数,学习JVM这种知识最大的用处就是为了面试,如果面试时可以说出这些知识就会让面试官感觉不错

该死,看来为了好工作,还是要把这些偏门的知识看看


这个帖子中有同学出了一组数据库相关的题目,我超过一半不会做,在自己出了题的帖子被别人题目打击,很没面子:(,但是我觉得自己没有办法把“不会回答”的责任推至对方出的题目,或者这些题目涉及的知识上太偏上,只能说我学习工作中没有接触到,或者使用过了但是没有注意总结形成自己的思想。而顶楼我发的题目与观点,大多是自己学习、使用的总结,并且以后工作上还需要经常用到的知识,所以我拿来发问,知识点偏与不偏,只是似乎人与角度而已。

每个人都有自己的观点,如果你觉得“对JAVA的认识有了一个新的高度!但人的精力是有限的,学习JVM这种知识最大的用处就是为了面试”,我可以认同这是你与不小的一部分开发者的想法,我不会这样想但也不会对这种想法表示不屑。我自己的看法是如果哪天我觉得“精力有限”,觉得接受新知识是种负担而不是一种乐趣,那可能我就该准备转管理方向了。

最后在帮知识二字喊一声冤枉:我国可能教育制度确实有很大偏颇,但只是培养和考察方式的责任,“恨屋及乌”的把各种知识没有道理,没有绝对无用的偏门知识,只有你不使用的知识。


顶你一次,顺便说下,如果连学习一大堆框架的时间都有了,怎么就没有学学基础知识的时间了,如果觉得这个知识很偏,那复习复习算法,操作系统,数据结构总可以吧,如果觉得这些都没用,那就得想想是现在没用还是以后都没用。中国基础软件和中间件产业发展是需要一些人才的。在我看来学习mina不如学学多线程,学习Hadoop不如学学算法和fork-join,学习spring不如学学面向对象,学习hibernate不如学学索引存储过程...
0 请登录后投票
   发表时间:2010-07-21  
IcyFenix 写道
linchao198401 写道
IcyFenix 写道
mogui258 写道
最后介绍一下自己的背景,在一间不大不小的上市软件公司担任平台架构师,有3年左右的面试官经验,工作主要方向是大规模企业级应用,参与过若干个亿元级的项目的底层架构工作。

3年面试经验,多少年工作经验??
总觉得楼主面试的这道面试题很难,10%的人能回答出都觉得很高了。
如果是10%,他们都又有多少年工作经验呢!
工作3年以下的应该很少有看 《深入jvm》 这本书的吧!



3年面试经验,多少年工作经验?? 
工作经验不好说,06年本科毕业,09年在职硕士毕业,但是本科没有毕业就已在公司工作的正式员工。

总觉得楼主面试的这道面试题很难,10%的人能回答出都觉得很高了。
确实,回答道第三点的,10%都不到,回答道第四点的几乎没有。

如果是10%,他们都又有多少年工作经验呢!
能回答道第三点的,应届生到工作10年的人都有。
工作经验某种程度上只能代表实践程度,应届生可能确实只能从书本上看来的,而社招应聘者可能是工作中、调优中用到时去学习的。天份与实践经验我都看重。

工作3年以下的应该很少有看 《深入jvm》 这本书的吧!
感觉论坛上好多人都看过。


楼主确实能力不错,工作四年,有这样的成就,而且平时的时间还去读研究生,可见对自己的人生有很好的规划,前途很好啊。

我工作五年了,可惜还发展的不好。

我最近在看数据库的知识。
我能随便问你些问题,然后你在不查资料的情况下,随便说说嘛?

因为我用的比较多的是MySQL和Oracle。
请问你这两个数据库熟悉吗?
知道事务吗?
事务有哪些隔离性?
事务的并发是怎么实现的?一般有几种你知道的实现方式?
你知道数据库的锁吗,有哪些锁类型,对于MySQL不同的引擎有哪些不同的锁机制。例如什么引擎有什么样的锁?

Oracle有哪些类型的锁?为什么说Oracle里面没有锁升级的概念?为什么MySQL里面需要锁升级?
Oracle和MySQL都用多版本并发控制也就Multi Versioning Concurrency Control。MVCC。能知道他是怎么样的一个机制吗?有什么样的好处?
对于不同的隔离性,哪些是可以使用MVCC,哪些是不能使用?

知道Latch,也就是闩,Oracle什么时候会用到呢?

为什么说有些数据库的锁加的越多,需要升级锁,因为锁对于哪些数据库是一种宝贵的资源,而对于Oracle来说确不是这样。Oracle是怎么做到的?
跟Java里面的锁有什么相同和不同的地方?
Java的Synchronized和Compare And Set有什么不同吗?什么时候会用Compare And Set,Java JDK里面有实现吗?
对于锁资源的管理来说,锁管理是怎么样的一个实现呢。是队列吗,是Hash吗?如果让你实现你会怎么实现?

我记得Java分配对象的时候也需要有某种锁,所以对于每个线程会预先提供一些内存空间,因为是线程内的,所以就不会和多线程竞争内存空间,你觉得我说的对吗?你有了解,能更清晰的解释这个机制吗?

期待你的解答。
同时我也可以多学点锁和同步并发,以及里面的实现等问题。
为以后的面试做准备。


已看到,现在下班,回家就回答一下,不GOOGLE。

公司有数据库组,所以数据库实在说不上擅长,很多题目都被问倒了@_@

------------------------------------------

我写完了,编译一下这楼,觉得自己回答得有点失败。

因为我用的比较多的是MySQL和Oracle。
请问你这两个数据库熟悉吗?


公司用Oracle,我自己做点小东西的时候比较乐意选择SQLite,MySQL没有用过,我只回答Oracle的吧。

知道事务吗?
呃,如果只是定义为知道而不是什么擅长、精通的话……我想应该能叫知道吧

事务有哪些隔离性?
串行、可重复读、读取已提交数据、读取未提交数据

事务的并发是怎么实现的?一般有几种你知道的实现方式?
是问乐观、悲观锁定吗?
实现方式一般是两种,一种是锁,一种MVCC。乐观锁其实不是数据库的实现之一,只是UPDATE的过程中发现WHERE原来的字段的值已经不存在了,然后UPDATE的更新条目为0,你的程序或者框架如果发现是0就会报错或者抛运行时异常。



你知道数据库的锁吗,有哪些锁类型,对于MySQL不同的引擎有哪些不同的锁机制。例如什么引擎有什么样的锁?

性质上来讲,共享和排他锁,范围上来讲,数据库级(SQLite只提供这个范围的锁)、表、行,也有称表级锁为DDL锁,行级为DML锁,Oracle里面根据性质和范围,组合成……呃TM、SX之类的几种锁,具体就不记得了。这个回答我知道不太准确@_@
我也记得不是很清楚,首先Oracle里面据说没有共享锁,只要你想要SELECT东西都是能SELECT得到的。锁分成TX,事务锁,TM所以,和DDL。TX就是事务的时候加锁,加锁的位置是在行的数据头里面,例如置1,这样其他事务如果要更改这一行会发现这个已经是1了,你只能等待。TM锁是当你要修改某行的数据,你需要在表的头加个锁,这个锁不允许其他DDL语句把整个表的结构改掉,例如删除列或者添加列。DDL锁是你在删除列或者添加列等其他操作的时候加的,这个锁可以保证其他DDL的操作等待。Oracle里面还有个Latch,也就是非常轻量级的锁,这个锁在共享池中使用,共享池会放编译解析过的SQL语句或者片段,所以设计添加和查询删除的操作,而且因为是共享的,所以需要有锁,这个锁是很轻量级的,你程序员是不能控制的,如果使用不当,锁会生成很多。例如如果你使用的是JDBC里面的Statement而不是PrepareStatement,就不能重用共享池里面的SQL语句。例如SELECT * FROM user WHERE userId=i。以及SELECT * FROM user WHERE userId= :id。第一个语句每次都发送拼出来的SQL语句,Oracle每次都需要进行解析,解析是很费CPU的。如果把每次解析的SQL放入共享池,因为整个数据库要共享的,所以Latch就会很多。

Oracle有哪些类型的锁?为什么说Oracle里面没有锁升级的概念?为什么MySQL里面需要锁升级?
当锁定数据过于密集,将会将锁升级一个范围级别。譬如一张表被一个链接锁定的行太多,将可能升级为表锁,这时候大粒度的锁定反而更加有效率。Oracle为什么没有锁升级这个答不上来……
Oracle没有锁升级一说,因为Oracle的锁是放到行的数据头里面,就如Java的对象的头里面有个锁的字节,Java里面也没有锁升级吧。MySQL需要锁升级是因为使用的是锁管理器。这个管理器会处理每次的锁请求,如果请求到来之后会在锁表里面搜索这个记录行的地址,就像HashMap一样,如果找不到这一行,那么就把这一行加上,如果表示这一行已经有事务加锁了。如果找到了这一行表示其他事务正在加锁,那么就把当前的事务加入到等锁的队列Queue里面,等待锁。所以如果请求的锁很多,事务又很多,整个锁管理器会耗费很多的内存来管理行地址和事务等待队列。如果你升级锁的粒度,那么使用的锁对象和事务等待队列就会小点的。但是仍然不是很好的扩展性。


Oracle和MySQL都用多版本并发控制也就Multi Versioning Concurrency Control。MVCC。能知道他是怎么样的一个机制吗?有什么样的好处?
对于不同的隔离性,哪些是可以使用MVCC,哪些是不能使用?

回答不上来……

知道Latch,也就是闩,Oracle什么时候会用到呢?
我只知道是比锁更小的锁钉单位,具体在数据库中的使用过程真的不了解。

为什么说有些数据库的锁加的越多,需要升级锁,因为锁对于哪些数据库是一种宝贵的资源,而对于Oracle来说确不是这样。Oracle是怎么做到的?
同上面问过的……不知道

跟Java里面的锁有什么相同和不同的地方?
Java的Synchronized和Compare And Set有什么不同吗?什么时候会用Compare And Set,Java JDK里面有实现吗?

终于熬到Java了,上面数据库太打击人,我决定明天拿去数据库组给他们耍一下。
Java并发我还好曾经给在部门做过这个培训,这方面擅长一些,同步是基于临界区互斥检测的,CAS是依赖系统本身保证比较-设置这个操作的原子性。JDK5之后提供了java.util.concurrent包,里面的原子int、原子long等就是基于CAS实现。
并没有一定必须使用CAS才能完成的场景,使用CAS的最大理由是基于性能考虑,但是有很多一定需要使用Synchronized才能完成的场景,譬如最简单的你要使用object.wait/notify。
跟我理解的差不多,其实操作系统里面已经有CAS的实现,只需要一条CPU原语就可以了,CPU比较内存地址中的值是否是compare的值,如果是就把那个值复制到寄存器,然后内存中的值设置成true,如果这个时候有其他线程,那么会发现内存为true,因为是原语,所以CPU那时候肯定只有执行一个语句,也就是CAS,其他线程没有办法中断,然后切换线程。对于多核的CPU应该也是一样,没有具体的了解过。因为只是一个CPU的原语,所以肯定是比同步速度快,但是也是有缺陷的,就是只能同步的更新内存位置上的值。所以对于不管是更新int,long还是reference一样。
CAS在JDK里面的实现是AtomicInteger等等的。

对于锁资源的管理来说,锁管理是怎么样的一个实现呢。是队列吗,是Hash吗?如果让你实现你会怎么实现?
不好意思,这个问能否描述得更清楚一些,锁资源管理是指?

我记得Java分配对象的时候也需要有某种锁,所以对于每个线程会预先提供一些内存空间,因为是线程内的,所以就不会和多线程竞争内存空间,你觉得我说的对吗?你有了解,能更清晰的解释这个机制吗?
我的观点是与你有较大差别:除非强制指定了volatile,不然多线程中各个线程对变量的操作并不会直接竞争同一块内存空间,线程有自己的工作内存作为主内存中与此线程相关对象的复制品,线程中的操作都相对于工作内存而言,数据的修改只有在工作内从中修改然后同步回主内存后,才能被各个线程共享。而Java中基于性能考虑,修改与刷新回主内存并不保证严格顺序,所以才会有单例DCL失败这样的事情,关于这个在我javaeye的博客上,去年写的单例模式有过相关的叙述:)
首先,我问的这个问题是发生在分配内存,也就是NEW的时候,你说的volatile如果没有读和取的话是不会需要这个的,你说的工作栈我也知道,但是这个是执行方法的时候才有的。对于NEW这个简单的动作,首先不需要用到volatile,然后不需要用到工作栈,而且创建的对象是不会放到栈里面的,栈只能放int,long等原型类型,对于对象只能放置reference。只要是NEW就会有竞争,多个线程NEW一个内存为什么会没有竞争呢?


期待你的解答。
同时我也可以多学点锁和同步并发,以及里面的实现等问题。
为以后的面试做准备。

也谢谢你的问题,Java部分我们可以继续交流,数据库部分我真的受打击了,握手。

 

其实数据库的问题主要还是集中在事务和锁上面,这些对于数据库的调优,完整性都是很重要的。

0 请登录后投票
   发表时间:2010-07-21  
linchao198401 写道

我记得Java分配对象的时候也需要有某种锁,所以对于每个线程会预先提供一些内存空间,因为是线程内的,所以就不会和多线程竞争内存空间,你觉得我说的对吗?你有了解,能更清晰的解释这个机制吗?


我的观点是与你有较大差别:除非强制指定了volatile,不然多线程中各个线程对变量的操作并不会直接竞争同一块内存空间,线程有自己的工作内存作为主内存中与此线程相关对象的复制品,线程中的操作都相对于工作内存而言,数据的修改只有在工作内从中修改然后同步回主内存后,才能被各个线程共享。而 Java中基于性能考虑,修改与刷新回主内存并不保证严格顺序,所以才会有单例DCL失败这样的事情,关于这个在我javaeye的博客上,去年写的单例模式有过相关的叙述:)


首先,我问的这个问题是发生在分配内存,也就是NEW的时候,你说的volatile如果没有读和取的话是不会需要这个的,你说的工作栈我也知道,但是这个是执行方法的时候才有的。对于NEW这个简单的动作,首先不需要用到volatile,然后不需要用到工作栈,而且创建的对象是不会放到栈里面的,栈只能放int,long等原型类型,对于对象只能放置reference。只要是NEW就会有竞争,多个线程NEW一个内存为什么会没有竞争呢?


@_@ 我来来回回看了几遍,始终没能理解为什么会忽然绕到栈上去。后面这段我写明确一些,在讨论的2个人思想完成偏离去2个方向就很无趣了。

先用英文标注一下我提到的几个概念:主内存:Main Memory、工作内存:Working Memory,这个与工作栈(Operand Stacks)完全是风马牛不相及的2个东西,Operand Stacks是方法调用时创建Frames中的一部分,两者一个描述多线程的内存模型,一个描述方法调用的模型。

在VM Spec(http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html)中,Threads and Locks章叙述了我们讨论的内容,如果JVM实现与VM Spec没有差异的话,那new一个对象的过程,会首先从主内存new出来,然后当线程(包括触发new动作的这个线程)使用他们时,需要申请复制到工作内存中后才被使用,复制到工作内存后,怎么对这个变量XXOO就是线程自己的事情了,其他线程看不见,只有线程切换时这个变量复制回主内存,其他线程才能看见。仅仅讲分配操作,new这个指令本身是原子的,“多个线程NEW一个内存为什么会没有竞争呢”这个描述本身不成立,因为new是原子的不能存在new到一半线程切换暂时不new了- -#(再明确一下,这里的new是指VM指令,而不是java的new关键字,vm的new指令只是分配内存,java那个new还要执行构造函数等一堆事情,编译后会变成一堆vm指令),也不能存在多个线程一起new(好吧,起码暂时还是一个时间一个线程在工作,随着多核CPU的出现,VM需要作出什么样的适应日后在探讨),所以new指令没有必要,也没有进行建立临界区,进行互斥锁定计数这些保护操作。另外,创建变量是原子的,但是复制的过程需要经过read-load-use-assign-store-write这一堆操作,这个过程就不是原子的(甚至还不保证严格顺序-_-#……DCL失败的原因)。

0 请登录后投票
   发表时间:2010-07-21   最后修改:2010-07-21
IcyFenix 写道
linchao198401 写道

我记得Java分配对象的时候也需要有某种锁,所以对于每个线程会预先提供一些内存空间,因为是线程内的,所以就不会和多线程竞争内存空间,你觉得我说的对吗?你有了解,能更清晰的解释这个机制吗?


我的观点是与你有较大差别:除非强制指定了volatile,不然多线程中各个线程对变量的操作并不会直接竞争同一块内存空间,线程有自己的工作内存作为主内存中与此线程相关对象的复制品,线程中的操作都相对于工作内存而言,数据的修改只有在工作内从中修改然后同步回主内存后,才能被各个线程共享。而 Java中基于性能考虑,修改与刷新回主内存并不保证严格顺序,所以才会有单例DCL失败这样的事情,关于这个在我javaeye的博客上,去年写的单例模式有过相关的叙述:)


首先,我问的这个问题是发生在分配内存,也就是NEW的时候,你说的volatile如果没有读和取的话是不会需要这个的,你说的工作栈我也知道,但是这个是执行方法的时候才有的。对于NEW这个简单的动作,首先不需要用到volatile,然后不需要用到工作栈,而且创建的对象是不会放到栈里面的,栈只能放int,long等原型类型,对于对象只能放置reference。只要是NEW就会有竞争,多个线程NEW一个内存为什么会没有竞争呢?


@_@ 我来来回回看了几遍,始终没能理解为什么会忽然绕到栈上去。后面这段我写明确一些,在讨论的2个人思想完成偏离去2个方向就很无趣了。

先用英文标注一下我提到的几个概念:主内存:Main Memory、工作内存:Working Memory,这个与工作栈(Operand Stacks)完全是风马牛不相及的2个东西,Operand Stacks是方法调用时创建Frames中的一部分,两者一个描述多线程的内存模型,一个描述方法调用的模型。

在VM Spec(http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html)中,Threads and Locks章叙述了我们讨论的内容,如果JVM实现与VM Spec没有差异的话,那new一个对象的过程,会首先从主内存new出来,然后当线程(包括触发new动作的这个线程)使用他们时,需要申请复制到工作内存中后才被使用,复制到工作内存后,怎么对这个变量XXOO就是线程自己的事情了,其他线程看不见,只有线程切换时这个变量复制回主内存,其他线程才能看见。仅仅讲分配操作,new这个指令本身是原子的,“多个线程NEW一个内存为什么会没有竞争呢”这个描述本身不成立,因为new是原子的不能存在new到一半线程切换暂时不new了- -#(再明确一下,这里的new是指VM指令,而不是java的new关键字,vm的new指令只是分配内存,java那个new还要执行构造函数等一堆事情,编译后会变成一堆vm指令),也不能存在多个线程一起new(好吧,起码暂时还是一个时间一个线程在工作,随着多核CPU的出现,VM需要作出什么样的适应日后在探讨),所以new指令没有必要,也没有进行建立临界区,进行互斥锁定计数这些保护操作。另外,创建变量是原子的,但是复制的过程需要经过read-load-use-assign-store-write这一堆操作,这个过程就不是原子的(甚至还不保证严格顺序-_-#……DCL失败的原因)。

 

 

首先,还是那个观点,内存只有一个,HEAP只有一个,如果多个线程,比如10个线程,同时运行NEW,Java字节码指定,VM原语。那么对于HEAP这样一个资源,如果10个线程不需要锁,不需要同步,那么是否他们都会去申请内存的最开始位置直到他们自己的size?也就是0 + offset。那么就是说多个线程将争抢HEAP中的同一块区域的内存地址,这样的情况下是否需要锁呢?因为如果那个对象是方法里面的变量,也就是线程栈里面才有的引用,也就是线程私有的,每个线程私有的内存地址空间是不共享的,所以需要锁来维持虚拟机发配内存的同步。

 

先不说NEW是放在队列里面,还是虚拟机怎么样其他实现的方式。如果让你实现,你怎么实现多个线程在NEW分配正确的内存空间。

首先内存空间分配有多种的匹配策略,跟操作系统一样的,比如

最适合策略,和申请空间的大小一样的空闲内存块可以直接使用。

最大策略,每次都从内存空闲块的最大空间中分配。

第一个匹配策略,遍历内存块中的空闲空间,发现有个空闲块,马上就使用他。

对于第一个匹配还有每次都从内存的开始位置遍历,或者下次的遍历开始的位置是从上次分配的内存空间的位置开始。

 

对于JVM,多个线程可能执行以上4种查找内存空间的策略,如果多个线程都在同一时间找到同一个内存空间,那么是否有竞争呢?有竞争不加锁,怎么知道那个资源是否被调用了呢?

 

JVM为了优化内存分配的时候的效率,不想加锁和检查锁,一开始的时候会为每个线程分配属于自己的Local Heap。跟Working Memory或者工作栈不是一样概念的,还是一个Heap,但是是线程专有的。只要是这个Heap里面分配的内存,线程就直接使用,不用担心别的线程会抢了他的内存或者有冲突。

当时线程本地堆空间有限,如果你申请的内存很大,JVM就会去Heap里面竞争了,然后是否继续延展本地堆空间的内存就看JVM的设计了。

 

我记得可能是《深入Java虚拟机》里面看到的。或者其他地方看到的。

目前先找到一个IBM的文档。

TLH

Thread Local Heap

http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=/com.ibm.java.doc.diagnostics.50/diag/understanding/mm_gc_coexist_threadlocal.html

 

你最后关于Volatile的用法是没有错的,但是我最开始问的问题是分配内存的时候,会不会加锁。

0 请登录后投票
   发表时间:2010-07-21  
linchao198401 写道
首先,还是那个观点,内存只有一个,HEAP只有一个,如果多个线程,比如10个线程,同时运行NEW,Java字节码指定,VM原语。那么对于HEAP 这样一个资源,如果10个线程不需要锁,不需要同步,那么是否他们都会去申请内存的最开始位置直到他们自己的size?也就是0 + offset。那么就是说多个线程将争抢HEAP中的同一块区域的内存地址,这样的情况下是否需要锁呢?因为如果那个对象是方法里面的变量,也就是线程栈 里面才有的引用,也就是线程私有的,每个线程私有的内存地址空间是不共享的,所以需要锁来维持虚拟机发配内存的同步。

 

分配过程我回复过了:先在主内存分配,然后复制到工作内存中。我们通俗一点理解吧,线程分配内存的时候,并不是线程自己去进行这个行为,而是告诉VM去做这个事情,1个线程在运作的时候,是1个vm去做这个事,100个线程在运作的时候,也是1个vm在做这个事情,并且vm还跟你保证了一定会要么没做分配,要做就把分配这个事情完整做完才会切换到别的线程。如果一定要按0+offest去理解,那offest这个值线程本身不知道,vm才知道。上面的描述是一种很不严谨的通俗,线程和vm本身不是对等的2个概念。

 

建议看看我发的那个地址,VM Spec把这个过程讲的很透彻。

0 请登录后投票
   发表时间:2010-07-21   最后修改:2010-07-21
IcyFenix 写道
linchao198401 写道
首先,还是那个观点,内存只有一个,HEAP只有一个,如果多个线程,比如10个线程,同时运行NEW,Java字节码指定,VM原语。那么对于HEAP 这样一个资源,如果10个线程不需要锁,不需要同步,那么是否他们都会去申请内存的最开始位置直到他们自己的size?也就是0 + offset。那么就是说多个线程将争抢HEAP中的同一块区域的内存地址,这样的情况下是否需要锁呢?因为如果那个对象是方法里面的变量,也就是线程栈 里面才有的引用,也就是线程私有的,每个线程私有的内存地址空间是不共享的,所以需要锁来维持虚拟机发配内存的同步。

 

分配过程我回复过了:先在主内存分配,然后复制到工作内存中。我们通俗一点理解吧,线程分配内存的时候,并不是线程自己去进行这个行为,而是告诉VM去做这个事情,1个线程在运作的时候,是1个vm去做这个事,100个线程在运作的时候,也是1个vm在做这个事情,并且vm还跟你保证了一定会要么没做分配,要做就把分配这个事情完整做完才会切换到别的线程。如果一定要按0+offest去理解,那offest这个值线程本身不知道,vm才知道。上面的描述是一种很不严谨的通俗,线程和vm本身不是对等的2个概念。

 

建议看看我发的那个地址,VM Spec把这个过程讲的很透彻。

 

 

我刚才发的帖子就是在讨论VM如何来分配内存。

你说100个线程,1个VM,是VM来决定应该如何分配,分配哪个内存地址空间给100个线程用。

 

首先想到的是两种实现方式:

1. 你说VM只有一个,线程有100多个,VM来处理100个线程的内存空间请求,那么就跟CPU一样,VM是否需要一个线程排队队列呢?因为VM只有一个,也就是说只要线程在申请内存地址的时候,所有线程一个一个来,VM一个一个分配,不能着急。那么VM就会成为线程申请内存的瓶颈。

2. 我同意VM和线程不是同一个概念,但是不是你理解的那样,VM里面有很多线程,当然GC也是线程之一,你的工作业务逻辑线程当然跟含有VM的线程不一样了,线程里面还有工作栈,我不知道GC里面是否有工作栈,两种线程应该是会有比较大的不同,也许是本地工作栈。线程是执行单元,VM是多个执行单元组合的一个进程。又不是客户端和服务器,为什么线程要跟VM请求空间?VM有个专门的线程来等待内存空间的申请?每个线程自己就是执行单位,就是一切,他知道怎么去申请内存空间,不需要跟VM申请,要申请的话,可能跟操作系统申请,如果线程是把内存的某个变量由0变为1,表示这个空间我拥有,假设再把线程的id放入内存的某个位置。这样每个线程就会自己去使用空间,每个线程自己去检查空间是否被使用了。我不知道为什么还有要告VM去做这件事情。按照你的说法,VM有个内存统一资源管理器。每个线程需要资源的时候要跟VM请求,这么说跟MySQL的锁资源管理器不就是一样了?

因为每个线程自己能处理分配和使用内存。所以就会出现多个线程竞争内存分配的事情发生。

不知道你看了我给你的链接没有,里面大概有说的一些。

 

然后你给我的链接,当然说的很透彻了,但是里面说的Java语言如何实现同步,说的不是JVM在分配内存的时候如何使得多个线程能得到自己的内存。这个是JVM的具体设计问题。可以统一内存分配管理器,也可以预先分配给每个线程内存Heap。

 

我把事情再放到点。

我们知道肯定是操作系统在分配内存,程序没有办法分配内存,需要内存的时候跟操作系统请求,对吧。那是每次需要内存的时候发信息给操作系统然后得到内存好呢,还是预先分配一些程序需要的内存,然后每个程序自己先用着呢。

 

我问的问题很简单,只是NEW的过程,甚至不包括返回到线程工作栈的这部分,所以你给我看的VM规范没有用。

 

你说你已经解释分配的过程了,但是我看到的是你说VM会分配好,然后线程就开始使用,复制到工作栈,然后修改返回。

但是就是没有说VM怎么分配,分配的时候会遇到什么事情。

0 请登录后投票
论坛首页 招聘求职版

跳转论坛:
Global site tag (gtag.js) - Google Analytics