10

I have a method (example below) which creates a new list, puts some stuff into it, and passes it along to another thread to operate on.

This seems thread safe. The list is local to the method which creates it. The method operates on the list and doesn't pass it to another thread until it is done operating on it.

But this feels wrong, because the list is accessed in two separate threads but it is not synchronized.

Is this acceptable thread-safe code?

class App
{
  public static void main(String[] args)
  {
    final ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(4);
    list.add(5);

    final ExecutorService es = Executors.newSingleThreadExecutor();
    es.execute(new Runnable() {
        @Override public void run()
        {
          for (Integer i : list)
            System.out.println(i);
        }});
    es.shutdown();
  }
}
4

2 回答 2

11

这是安全的,因为一个线程写入列表,然后另一个线程从列表中读取,并且执行器服务在您提交任务时保证发生之前的关系。

从文档中引用:

java.util.concurrent 及其子包中所有类的方法将这些保证扩展到更高级别的同步。尤其是:

[...]

在将 Runnable 提交给 Executor 之前,线程中的操作发生在其执行开始之前。对于提交给 ExecutorService 的 Callables 也是如此。

于 2013-01-24T22:44:29.987 回答
1

这是线程安全的,是的,因为它main正在创建这个线程,因为它正在构建启动底层线程的执行器,并且因为它通过一个BlockingQueue同步的。

你需要注意的是:

  1. 将列表传递给对象构造函数内部的线程,因为 JIT 能够优化构造函数外部的字段初始化。

  2. 将列表传递给另一个线程而不进行同步。例如,如果一个线程初始化列表,然后将其设置在可从另一个线程访问的本地字段上。

于 2013-01-24T22:44:50.350 回答