s********e 发帖数: 340 | 1 Question:
A J2SE 5.0 class ThirdPartyObject, that is not thread-safe, is to be used
in some new java code. Which of the following design decision can be made to
ensure that no race condition will occour?
A. Store instance of ThirdPartyObject in a ThreadLocal
B. Provide a static getter for a ThirdPartyObject instance
C. Ensure that an instance of ThirdPartyObject is private and can only be
accessed using a public getter method
D Make any instance of ThirdParyObject a local(method) variable and ensure
that no reference to it are published
E. Use @Immutable as an annotation with ThirdPartyObject instances.
ABCDE 请问大家会选哪个,或那几个?
请说明为什么?
谢谢! |
s****y 发帖数: 503 | |
c******3 发帖数: 296 | |
z****e 发帖数: 54598 | |
s****y 发帖数: 503 | 5
为什么A D不对?
【在 z****e 的大作中提到】 : E
|
h*****k 发帖数: 15 | 6 万一里面有static a和d就不行了吧?
★ 发自iPhone App: ChineseWeb 7.8
【在 s****y 的大作中提到】 : : 为什么A D不对?
|
z****e 发帖数: 54598 | 7 abcd都只控制了对stack里面地址这个value的访问
并没有控制对heap那一块的访问
其他线程只要能reference过去,就能不受约束地修改heap里面的值
这个时候线程访问的话,就会冲突
immutable其实并没有控制访问,但是immutable就不允许改变
那并发冲突也就不存在了
【在 s****y 的大作中提到】 : : 为什么A D不对?
|
s****y 发帖数: 503 | 8 但是D里面有 ensure that no reference to it are published
这样是不是其他线程就得不到reference了? |
z****e 发帖数: 54598 | 9 local variable就是passed by reference
就是传入一个reference的拷贝
本身就是拷贝了,所以前半句话已经错了
再不reference to it就没有任何意义
另外reference只是其中一种方式
直接clone()可以取得一个reference的拷贝
最后reference不会有任何值指向stack里面的位置
全部都指向heap的位置,reference互相传递是拷贝reference value
Integer i = new Integer(0);
Integer j = i;
这个时候i和j都存的是一个地址,0x00232...比如说
这两个地址都是heap里面对象的位置,而j不会指向i
所以后半句话等于没说,java不会有指向stack地址的变量
所以这个怎么看都是错的
【在 s****y 的大作中提到】 : 但是D里面有 ensure that no reference to it are published : 这样是不是其他线程就得不到reference了?
|
j*****8 发帖数: 3635 | 10 如果在method里这么定义一个数组,那它是存在堆上还是栈上?
int[] data = {2,3,4};
【在 z****e 的大作中提到】 : abcd都只控制了对stack里面地址这个value的访问 : 并没有控制对heap那一块的访问 : 其他线程只要能reference过去,就能不受约束地修改heap里面的值 : 这个时候线程访问的话,就会冲突 : immutable其实并没有控制访问,但是immutable就不允许改变 : 那并发冲突也就不存在了
|
|
|
z****e 发帖数: 54598 | 11 java数组是object
在堆上存对象主体
在stack上存地址
【在 j*****8 的大作中提到】 : 如果在method里这么定义一个数组,那它是存在堆上还是栈上? : int[] data = {2,3,4};
|
j*****8 发帖数: 3635 | 12 那就是说所有object,不管是通过new创建的还是别的渠道创建的,都是存在堆上;栈
上只会存reference?
【在 z****e 的大作中提到】 : java数组是object : 在堆上存对象主体 : 在stack上存地址
|
z****e 发帖数: 54598 | 13 所有的object应该不是,一些临时变量会放在stack上
inline的一些方法块有可能会被放在stack上
【在 j*****8 的大作中提到】 : 那就是说所有object,不管是通过new创建的还是别的渠道创建的,都是存在堆上;栈 : 上只会存reference?
|
j*****8 发帖数: 3635 | 14 tks
回到lz问题里的d,如果在一个方法内定义了一个local object,给出假设前提说不会
暴露这个object到方法外的话,那应该是thread safe的。
【在 z****e 的大作中提到】 : 所有的object应该不是,一些临时变量会放在stack上 : inline的一些方法块有可能会被放在stack上
|
z****e 发帖数: 54598 | 15 在local object里面塞一个static成员
【在 j*****8 的大作中提到】 : tks : 回到lz问题里的d,如果在一个方法内定义了一个local object,给出假设前提说不会 : 暴露这个object到方法外的话,那应该是thread safe的。
|
r***s 发帖数: 737 | 16 面试里这种问题都是考你继续提问的本事
不是回答一个答案就完。
用thread local 虽然有可能有指针泄露到其他线程。
可这不是非常容易。很多时候可以避免的。
D 现在不少IDE有escape analysis 保证没有指针泄露到
Method 外面, 也是可行的
E 功能上限制不少,很多时候不适用
总之是要展开讨论,不是给个答案就完了。
【在 z****e 的大作中提到】 : abcd都只控制了对stack里面地址这个value的访问 : 并没有控制对heap那一块的访问 : 其他线程只要能reference过去,就能不受约束地修改heap里面的值 : 这个时候线程访问的话,就会冲突 : immutable其实并没有控制访问,但是immutable就不允许改变 : 那并发冲突也就不存在了
|
w****r 发帖数: 15252 | |
t***t 发帖数: 6066 | |
r***s 发帖数: 737 | 19 local variable 不是传进来的,你理解错了
【在 z****e 的大作中提到】 : local variable就是passed by reference : 就是传入一个reference的拷贝 : 本身就是拷贝了,所以前半句话已经错了 : 再不reference to it就没有任何意义 : 另外reference只是其中一种方式 : 直接clone()可以取得一个reference的拷贝 : 最后reference不会有任何值指向stack里面的位置 : 全部都指向heap的位置,reference互相传递是拷贝reference value : Integer i = new Integer(0); : Integer j = i;
|
r***s 发帖数: 737 | 20 你实现immutable也有一样的问题。
就算所有的field都是final,
transitive state还是有可能被修改
【在 z****e 的大作中提到】 : 在local object里面塞一个static成员
|
|
|
r***s 发帖数: 737 | 21 D 里说的就是所有的 ThirdPartyObject都是临时变量,不会跑出去。
【在 z****e 的大作中提到】 : 所有的object应该不是,一些临时变量会放在stack上 : inline的一些方法块有可能会被放在stack上
|
z****e 发帖数: 54598 | 22 如果把涉及所有的sub class全部immutable了之后
就没这个问题了
【在 r***s 的大作中提到】 : 你实现immutable也有一样的问题。 : 就算所有的field都是final, : transitive state还是有可能被修改
|
z****e 发帖数: 54598 | 23 跑不跑出去都只限制了stack里面的访问权限
heap只要能被reference到就会出现并发冲突
丢给d一个static就挂了
所有选择看,显然e是最合适的答案
也许e不严密,本来很多java问题就不是那么严谨
如果对方要深入讨论,那就展开
就像用==比较enum一样,理论上可以,但是具体到垮虚拟机的操作的时候
就会出问题,所以很多java问题都是用最nc最简单的方法就好了
比如对于非primitive types的比较,一律用.equals方法
比如对于线程安全,只要是非thread safe类/对象,如有需要
多线程环境一律用synchronized关键字
这些东西深究下去一知半解的反而容易出错
jvm的实现本来就不是啥必修
【在 r***s 的大作中提到】 : D 里说的就是所有的 ThirdPartyObject都是临时变量,不会跑出去。
|
r***s 发帖数: 737 | 24 final HashMap fieldC;
fieldC指向的object状态是可修改的。
【在 z****e 的大作中提到】 : 如果把涉及所有的sub class全部immutable了之后 : 就没这个问题了
|
z****e 发帖数: 54598 | 25 因为HashMap本身不是immutable的
你自己写一个MyHashMap extends HashMap
然后加一个Immutble annotation就好了
用这个类
【在 r***s 的大作中提到】 : final HashMap fieldC; : fieldC指向的object状态是可修改的。
|
r***s 发帖数: 737 | 26 void TempMethod() {
ThirdPartyObject localRef = new ThirdPartyObject();
localRef.DoWork();
return;
}
在DoWork里面没有把自指针交给别人的情况下,是不会有任何问题的
static field在java概念里面属于class,不属于object。那是一个global state而不是
object state 因为即使在
一个object都没有的情况下static也存在。
另外你用 final static LinkedList sFld = new LinkedList
所以我说这个题原来就是展开谈话的一种方式,单纯给任何一个答案都不是
人家想要的。
【在 z****e 的大作中提到】 : 跑不跑出去都只限制了stack里面的访问权限 : heap只要能被reference到就会出现并发冲突 : 丢给d一个static就挂了 : 所有选择看,显然e是最合适的答案 : 也许e不严密,本来很多java问题就不是那么严谨 : 如果对方要深入讨论,那就展开 : 就像用==比较enum一样,理论上可以,但是具体到垮虚拟机的操作的时候 : 就会出问题,所以很多java问题都是用最nc最简单的方法就好了 : 比如对于非primitive types的比较,一律用.equals方法 : 比如对于线程安全,只要是非thread safe类/对象,如有需要
|
z****e 发帖数: 54598 | 27 static所处的方法区在最新的jvm impl里面已经被划归到了heap中去了
你就算说它不属于object,就算ide会抛warning,你还是不能改变一个事实
就是写代码可以通过object访问static成员,而且干活的时候这种写法还不少见
static成员也是在类加载的时候才会放入内存,又不是说上来就往内存里面放
多线程环境里面访问static成员也不是什么新鲜事
properties就很喜欢扔给static去存放,而且还都是public final的
这就是immutable
说到底控制的都只是stack的权限,其实多线程说白了,要想控制并发冲突
最简单的就是加synchronized关键字,这个就是对heap加锁做控制
@Immutable这个annotation在jpa中用得比较多
其实现依赖于entity framework本身,你需要一个类似hibernate一样的东西
那怎么写,还不是你自己控制的,immutable这个annotation只是一个标示
本身并不确保这个class是immutable的,但是一般你这么写
就依赖了一个framework,比如hibernate,hibernate会帮忙控制住写权限
其实java深入下去很多东西都不是那么严格,反正都可以argue
在某一些特定环境下,你可以通过java自带的工具“黑”掉很多规则
比如private,singleton,你这个内存地址一样可以通过反射取出来
甚至配合annotation,都可以自动弹出来
如果对方纠结,那就跟他解释就是了
其实这题最核心的思路就是要控制住heap上的写权限
不是
【在 r***s 的大作中提到】 : void TempMethod() { : ThirdPartyObject localRef = new ThirdPartyObject(); : localRef.DoWork(); : return; : } : 在DoWork里面没有把自指针交给别人的情况下,是不会有任何问题的 : static field在java概念里面属于class,不属于object。那是一个global state而不是 : object state 因为即使在 : 一个object都没有的情况下static也存在。 : 另外你用 final static LinkedList sFld = new LinkedList
|
g*****g 发帖数: 34805 | 28 A is closest, and even A is not guaranteed to be safe. Consider an object
like this. As long as 2 threads are using it, it's not safe;
class ThirdPartyObject {
private static int a = 1;
private static int dup() { return a + a};
} |
s********e 发帖数: 340 | 29 谢谢大家的讨论,我个人认为应该选A和C 啊?
A放到ThreadLocal里,各个线程间就不存在资源竞争了,各个线程保存自己的资源。
C,是因为类只有Get方法了,那就是只读了,也不错资源竞争了。
D 我认为错的原因是,如果没有reference指向这个实例,那么这个实例就成垃圾啊
E,@Immutable只是一个注释,并不能改变程序的啊。
【在 z****e 的大作中提到】 : local variable就是passed by reference : 就是传入一个reference的拷贝 : 本身就是拷贝了,所以前半句话已经错了 : 再不reference to it就没有任何意义 : 另外reference只是其中一种方式 : 直接clone()可以取得一个reference的拷贝 : 最后reference不会有任何值指向stack里面的位置 : 全部都指向heap的位置,reference互相传递是拷贝reference value : Integer i = new Integer(0); : Integer j = i;
|
c******3 发帖数: 296 | 30 A不对,因为无法保证同一instance不会用到其他threads里
C也不对,因为getter拿到后,谁都可以改。
D不对,因为不保证ThirdPartyObject 不开后门。 |
|
|
a***u 发帖数: 36 | 31 A D 吧
C当然不行,因为不同的thread 可同时通过getter修改同一个object
E Immutable 没用过这annotation, 有吗?如果这就是final的reference,是不行的,
它指向的object 可以随便改 |