我的自定义异步任务是否应该同步访问传递给构造函数的内容?

时间:2012-11-16 10:31:35

标签: java concurrency synchronization

假设我有一个不可变的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线程上创建了ModelTask个实例。但是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上运行。

3 个答案:

答案 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)
  •   

这正是我所寻找的!