我经常看到这样的代码:
Listener mListener;
public void setListener(Listener listener){
mListener=listener;
}
public void fooFunction(){
...
...
if (mListener!=null){
mListener.notifyFoo();
}
}
我的问题是:如果在null检查和notifyFoo()之间,另一个线程调用setListener(null),该怎么办?这可能吗?还是编译器使其成为原子
您可以同步方法
public synchronized void setListener(Listener listener){
mListener=listener;
}
public synchronized void fooFunction(){
...
...
if (mListener!=null){
mListener.notifyFoo();
}
}
或者如果你想要更好的锁粒度
private Object monitor = new Object();
public void setListener(Listener listener){
synchronized (monitor) {
mListener=listener;
}
}
public void fooFunction(){
...
...
synchronized (monitor) {
if (mListener!=null){
mListener.notifyFoo();
}
}
}
您可以通过使块同步来避免这种情况
public synchronized void setListener(Listener listener) {
....
}
public synchronized void fooFunction() {
....
}
默认情况下,编译器不生成任何原子。的确,在两行之间有可能将侦听器设置为null
。您可以使用synchronized
来避免这种情况。
这里的同步太夸张了。在检查null
:之前,只需复制成员变量
Listener mListener;
public void setListener(Listener listener){
mListener=listener;
}
public void fooFunction(){
...
...
Listener listener = mListener;
if (listener!=null){
listener.notifyFoo();
}
}
是的,有可能。将您的fooFunction和setListener标记为同步,它应该使此代码成为多线程安全的