无状态种在并发环境中绝对安全吗
无状态类在并发环境中绝对安全吗?
无状态类是指一个对象没有任何属性,就像下面这个类一样,通常来说无状态的类在并发环境中比较安全:
<span style="white-space: pre;">dosomething方法执行过程在jvm中表示为:</span>
<br><img src="http://dl.iteye.com/upload/attachment/451594/5e9212ec-7baa-32a0-a89f-41b7e49b4e3c.jpg" alt="">
这样看起来,即使对象vector1和对象vector2保存在堆上对所有栈可见,但是能够访问它们的引用局限在栈中,所以栈1只能访问vector1,栈2只能访问vector2,而且当方法执行完毕,对象vector1和对象vector2很快失去“重力”,被垃圾回收掉。
但是,有没有这样一种可能,在<span style="white-space: pre;">dosomething方法的执行过程中,两个vector引用指向同一个vector对象,那么这时候,就有可能出现问题,为了达到这个目的,</span>
<span style="white-space: pre;">看下面的程序:</span>
<span style="white-space: pre;">然后让main线程和thread0线程交替执行,最后输出结果为:[cantellow, cantellow]</span>
虽然正常run程序的话,只输出[cantellow],但是不排除上面的可能,特别是在大型应用程序中。
所以,无状态的类在并发情况中不能说是绝对安全的,一般静态变量对象是很容易被共享出来的,即使这个静态变量本身是线程安全的(vector),也不能保证它被多个栈引用时能确保正确的行为。
对于有状态的类我们很谨慎,因为有状态就意味着对象中的方法能够任意访问它,对于无状态的类来说,我们也需要谨慎对待,因为无状态类的方法很可能获取堆上其他已存在对象的引用,而不是重新生成对象,当这个对象是唯一的时候(静态变量很容易做到这一点),如果我们不对此方法进行同步或者协调,那么很可能,就会出现并发问题。
同样的道理,你也不能说不可变类在并发环境中是安全的。
无状态类是指一个对象没有任何属性,就像下面这个类一样,通常来说无状态的类在并发环境中比较安全:
class class1 { public void dosomething() { vector<string> vector = new vector<string>(); string element = ""; if (!vector.contains(element)) { vector.add(element); } } }
<span style="white-space: pre;">dosomething方法执行过程在jvm中表示为:</span>
<br><img src="http://dl.iteye.com/upload/attachment/451594/5e9212ec-7baa-32a0-a89f-41b7e49b4e3c.jpg" alt="">
这样看起来,即使对象vector1和对象vector2保存在堆上对所有栈可见,但是能够访问它们的引用局限在栈中,所以栈1只能访问vector1,栈2只能访问vector2,而且当方法执行完毕,对象vector1和对象vector2很快失去“重力”,被垃圾回收掉。
但是,有没有这样一种可能,在<span style="white-space: pre;">dosomething方法的执行过程中,两个vector引用指向同一个vector对象,那么这时候,就有可能出现问题,为了达到这个目的,</span>
<span style="white-space: pre;">看下面的程序:</span>
public class class2 { private static vector<string> vector = new vector<string>(); public vector<string> getvector() { return vector; } public static void main(string[] args) { class3 c = new class3(); thread t = new thread(new runnable() { public void run() { class3 c = new class3(); c.dosomething(); } }); t.start(); c.dosomething(); system.out.println(vector); }}
class class3 { public void dosomething() { vector<string> vector; class2 c = new class2(); vector = c.getvector(); string element = "cantellow"; if (!vector.contains(element)) {//在此处打上断点 vector.add(element); } }}用eclipse在<span style="white-space: pre;">if (!vector.contains(element))打上断点,</span>
<span style="white-space: pre;">然后让main线程和thread0线程交替执行,最后输出结果为:[cantellow, cantellow]</span>
虽然正常run程序的话,只输出[cantellow],但是不排除上面的可能,特别是在大型应用程序中。
所以,无状态的类在并发情况中不能说是绝对安全的,一般静态变量对象是很容易被共享出来的,即使这个静态变量本身是线程安全的(vector),也不能保证它被多个栈引用时能确保正确的行为。
对于有状态的类我们很谨慎,因为有状态就意味着对象中的方法能够任意访问它,对于无状态的类来说,我们也需要谨慎对待,因为无状态类的方法很可能获取堆上其他已存在对象的引用,而不是重新生成对象,当这个对象是唯一的时候(静态变量很容易做到这一点),如果我们不对此方法进行同步或者协调,那么很可能,就会出现并发问题。
同样的道理,你也不能说不可变类在并发环境中是安全的。