Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
  }
}
like image 912
Dijkstra Avatar asked Jan 24 '13 22:01

Dijkstra


People also ask

Are local objects thread-safe?

If an object created locally never escapes the method it was created in, it is thread-safe. In fact, you can also pass it on to other methods and objects as long as none of these methods or objects make the passed object available to other threads.

How can you make an object thread-safe?

Using Atomic Variable Using an atomic variable is another way to achieve thread-safety in java. When variables are shared by multiple threads, the atomic variable ensures that threads don't crash into each other.

Are local variables in static method thread-safe?

Local variables are stored in each thread's own stack. That means that local variables are never shared between threads. That also means that all local primitive variables are thread safe.

Can threads have local variables?

The local variables of a function are unique to each thread that runs the function. However, the static and global variables are shared by all threads in the process. With thread local storage (TLS), you can provide unique data for each thread that the process can access using a global index.


2 Answers

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.

like image 89
JB Nizet Avatar answered Oct 10 '22 17:10

JB Nizet


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.

like image 34
Gray Avatar answered Oct 10 '22 16:10

Gray