案例
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
public void doSomeThings() {
if(b != null) {
//此处即使做了非空判断,多线程时也不能保证在执行b的方法时b不空
b.doSomeThings();
}
}
}
A a = new A();
B b = new B();
a.setB(b);
new Thread() {
void run() {
a.setB(null);
}
}.start();
new Thread() {
void run() {
a.doSomeThings();
}
}.start();
代码如上,多线程访问A的对象a,为了确保线程安全,常用的方法是加锁。比如下面这样:
public synchronized void setB(B b) {
this.b = b;
}
public synchronized void doSomeThings() {
if(b != null) {
b.doSomeThings();
}
}
新方法
现在介绍一种新方法
public void doSomeThings() {
B tmpB = b;
if(tmpB != null) {
tmpB.doSomeThings();
}
}
将b赋值给一个局部变量tmpB,在执行B方法前判断tmpB是否为空。
上述方法中,将b赋值给一个局部变量tmpB时如果b不空,那么在执行tmpB.doSomeThings()
时即使b被置空了,tmpB也不会为空。而且tmpB是一个局部变量,当A.doSomeThings()方法执行完后就释放了,所以不会造成内存泄漏。
但是该方法要求A.doSomeThings()不能在短时间内被频繁调用,否则会产生大量的局部变量,这些局部变量又会被一下子回收,造成内存抖动。