2013-01-24 3 views
9

Ho un metodo (esempio sotto) che crea un nuovo elenco, inserisce alcune cose e lo passa ad un altro thread su cui operare.Passare un nuovo oggetto locale a un thread, thread-safe?

Questo thread sembra sicuro. L'elenco è locale al metodo che lo crea. Il metodo funziona sull'elenco e non lo passa a un altro thread finché non viene eseguito su di esso.

Ma questo si sente in errore, poiché l'elenco è accessibile in due thread separati ma non è sincronizzato.

È accettabile questo codice thread-safe?

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

risposta

10

E 'sicuro perché un thread scrive alla lista, poi un altro thread legge dalla lista, e il servizio esecutore garantisce un rapporto succedere, prima, quando si invia un compito.

preventivo da the documentation:

I metodi di tutte le classi di java.util.concurrent ei suoi sottopacchetti estendere tali garanzie di sincronizzazione di livello superiore. In particolare :

[...]

azioni in un filo prima della presentazione di un Runnable all'esecutore accadere-prima dell'inizio sua esecuzione. Analogamente per Callables inviato a un ExecutorService.

1

Questo è thread-safe, sì perché questo è maincreando questa discussione perché sta costruendo l'esecutore che inizia il filo conduttore e perché passa attraverso un BlockingQueue sincronizzato.

Quello che dovete stare attenti è:

  1. passando una lista fuori ad un filo all'interno di un costruttore di oggetto dal momento che il JIT è in grado di ottimizzare l'inizializzazione campo di fuori il costruttore.

  2. Passare l'elenco a un altro thread senza sincronizzazione. Ad esempio, se un thread inizializza l'elenco e lo imposta su un campo locale accessibile da un altro thread.