【发布时间】:2015-12-22 13:28:52
【问题描述】:
我有一个 singleton 类MyService,它有两个函数可以从/向文件读取和写入数据:
public class MyService {
private static MyService instance;
private MyFileAccessor fileAccessor;
private MyService() {
fileAccessor = new MyFileAccessor();
}
public static MyService getInstance() {
if (instance == null) {
instance = new MyService();
}
return instance;
}
// write data to file through fileAccessor object
public void writeDataToFile(Object data){
fileAccessor.writeToFile(data);
}
// read data from file through fileAccessor object
public Object readFile() {
return fileAccessor.readFromFile();
}
}
MyFileAccessor 类具有同步函数来读写文件:
public class MyFileAccessor {
private File mFile;
public MyFileAccessor() {
mFile = new File(PATH);
}
public synchronized Object readFromFile() {
// code to read mFile
…
}
public synchronized void writeToFile(Object data) {
// code to write data to mFile
…
}
}
我的问题:当我的项目通过它从/向文件读取和写入数据时,单身MyService 类线程安全吗?是否存在潜在的并发问题?
===== 更新 ===
基于答案的另外两个问题:
Q1。我看到了下面关于使用 Initialized-On-Demand idom 的答案。但是如果我只在getInstance() static 方法上使用synchronized 关键字还不够吗?
public static synchronized MyService getInstance() {
...
}
不是也让单例实例创建原子化了吗?
Q2.如果我只使用 MyFileAccessor 到 MyService 实例,是否仍然需要将 MyFileAccessor 设为单例或在 MyFileAccessor.class 上同步?我的意思是 MyService 是一个单例,不是已经保证只有一个实例能够调用MyFileAccessor 中的方法吗?
【问题讨论】:
-
这不是一个单例,因为您对
instance == null的检查并可能分配instance = new MyService()不是原子完成的。查看Initialization-on-demand idiom。 -
@AndyTurner,你的意思是当多个线程调用
MyService.getInstance()时,它不是线程安全的吗?如果是这样,如何使其安全? -
@Leem.fin 是的。 “查看按需初始化习语。”。
-
你应该将
mFile设为final,以保证它对所有线程的可见性。
标签: java multithreading java-threads