假设我的网络应用程序中有一个名为“Foo”的课程。它有一个initialise()方法,当使用Spring创建bean时调用该方法。然后,initialise()方法尝试加载外部服务并将其分配给字段。如果无法联系该服务,则该字段将设置为null。
private Service service;
public void initialise() {
// load external service
// set field to the loaded service if contacted
// set to field to null if service could not be contacted
}
当有人在类“Foo”上调用方法get()时,如果在initialise()方法中启动了服务,则会调用该服务。如果服务的字段为null,我想尝试加载外部服务。
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
如果我这样做,可能会出现同步问题吗?
答案 0 :(得分:1)
工具包的答案是正确的。要解决这个问题,只需声明你的Foo的initialise()方法是同步的。你可以将Foo重构为:
private Service service;
public synchronized void initialise() {
if (service == null) {
// load external service
// set field to the loaded service if contacted
}
}
public String get() {
if (service == null) {
initialise(); // try and load the service again
}
// perform operation on the service is service is not null
}
答案 1 :(得分:0)
是的,您将遇到同步问题。
让我们假设你有一个servlet:
public class FooServlet extends HttpServlet {
private MyBean myBean;
public void init() {
myBean = (MyBean) WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext()).getBean("myBean");
}
public void doGet(HttpRequest request, HttpResponse response) {
String string = myBean.get();
....
}
}
class MyBean {
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
你的bean定义如下:
<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />
问题是你的servlet实例被多个请求线程使用。因此,由service == null保护的代码块可以由多个线程输入。
最好的修复(避免双重检查锁定等)是:
class MyBean {
public synchronized String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
希望这是有道理的。如果没有,请发表评论。