假设我有一个不可变的Model
类:
class Model {
final String id;
Model(String id) {
this.id = id;
}
}
我有一个自定义的Task
课程:
class Task extends BlaBlaTask {
final Model model;
Task(Model model) {
this.model = model;
}
// runs on a background thread
void doInBackground() {
// do smth with model, e.g.:
String id = model.id;
}
}
并且在主UI线程上创建了Model
和Task
个实例。但是doInBackground()
在另一个线程上运行。这段代码错了吗?我应该添加同步,例如像这样的东西:
class Task extends BlaBlaTask {
Model model;
Task(Model model) {
setModel(model);
}
// runs on a background thread
void doInBackground() {
// do smth with model, e.g.:
String id = getModel().id;
}
private synchronized void setModel(Model m) {
model = m;
}
private synchronized Model getModel() {
return model;
}
}
P.S。我正在研究Java 1.4,代码可能可以在多核CPU上运行。
答案 0 :(得分:2)
我不再熟悉Java 1.4的Java内存模型,但我不明白为什么需要同步。
如果您正在启动一个线程,那么新线程将在启动线程之前看到您编写的所有内容。
如果您将任务传递给现有线程,则发布机制应具有所有必要的同步,以确保线程可以看到在发布之前已编写的所有内容。这不应该是同步任务的任务,它应该是Queue的工作(或者用于将任务从一个线程传递到另一个线程的任何其他方式)
答案 1 :(得分:1)
如果在后台线程启动之前已经实例化了Task
(以及它之前的Model
),那么肯定没有必要进行同步。如果线程已在运行并且您只是向它提交任务,并且您没有从Java 5的final
语义中受益,理论上可能存在问题,但实际上不太可能实际发生。
答案 2 :(得分:0)
AsyncTask API现在有明确的通知:
记忆可观察性
AsyncTask保证所有回调调用都是同步的 以下操作在没有明确的情况下是安全的方式 同步。
- 在构造函数或
onPreExecute()
中设置成员字段,并参阅 他们在doInBackground(Params...)
。- 在
doInBackground(Params...)
中设置成员字段,并在其中引用它们onProgressUpdate(Progress...)
和onPostExecute(Result)
。
这正是我所寻找的!