Dijkstra
Dijkstra

Reputation: 333

Passing a local new object to a thread, thread safe?

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();
  }
}

Upvotes: 10

Views: 1002

Answers (2)

Gray
Gray

Reputation: 116878

This is thread-safe, yes because this main is creating this thread because it is constructing the executor which starts the underlying thread and because it goes through a BlockingQueue which is synchronized.

What you need to be careful of is:

  1. Passing a list off to a thread inside of an object constructor since the JIT is able to optimize field initialization outside the constructor.

  2. Passing the list to another thread without synchronization. For example if one thread initializes the list and then sets it on a local field which is accessible from another thread.

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691715

It's safe because one thread writes to the list, then one other thread reads from the list, and the executor service guarantees a happen-before relationship when you submit a task.

Quote from the documentation:

The methods of all classes in java.util.concurrent and its subpackages extend these guarantees to higher-level synchronization. In particular:

[...]

Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. Similarly for Callables submitted to an ExecutorService.

Upvotes: 11

Related Questions