9

Domanda ho avuto per anni: In questo pseudocodice,Does .awaitTermination() stabilisce che succede prima con il lavoro eseguito nell'esecutore?

ExecutorService svc = Executors.newFixedThreadPool(3); 
svc.submit(new Runnable() { /* code A */ }); 
svc.shutdown(); 
if(svc.awaitTermination(...)) { 
    // code B 

.awaitTermination() non è documentato come stabilire accade-prima tra il codice A & B. C'è una ragione che non è?

I ExecutorService e concurrent package javadocs definiscono accade-prima tra i compiti e il lavoro svolto prima che sono state presentate, ma non tra i compiti esecutore e codice dopo il successo .awaitTermination() chiamata.

Nota, non sto chiedendo critiche di progettazione su come ristrutturare il mio codice per sfruttare le relazioni documentate precedenti. La mia domanda qui è, c'è una ragione per cui i documenti non menzionano l'accaduto - prima in questa situazione?

(Si noti che questo non è un duplicato di 22665198 nonostante il titolo molto appropriato.)

+0

La logica impone che ci debba essere un caso prima di ordinare, ma hai ragione OP, non riesco a trovarlo documentato da nessuna parte. –

+1

L'unica garanzia "ufficiale" è che se si recupera il futuro con 'Future f = svc.submit (...)' E si chiama 'f.get()', quindi si ha la relazione hb. – assylias

+0

@assylias quindi, perché è quello? Devo davvero '.get()' ogni compito? So di aver scritto un sacco di codice che presuppone che un successo '.awaitTermination()' stabilisce * succede-prima *. – tariksbl

risposta

1

ExecutionService, sei sicuro? Intendevi ExecutorService? Inoltre, non esiste un metodo ExecutorService.awaitTermination() senza parametri. Il metodo ExecutorService.awaitTermination(long, TimeUnit) riceve il tempo di attesa del timeout. Ovviamente, se ritorna a causa del timeout, non può garantire la relazione prima, quindi non può pubblicizzare questa garanzia nel suo contratto, perché non è presente in tutti i casi.

+3

Perché i Javadoc non possono dire * Se questa chiamata ritorna normalmente, stabilisce un caso prima di ordinare *? –

+0

Risolto il mio pseudocodice, grazie. – tariksbl

+0

@JohnVint Perché questa informazione sarebbe inutile, come sarebbe noto solo in fase di esecuzione.Devi fare affidamento su questo ordine per scrivere il codice corretto in primo luogo. –

-1

In realtà si sono sbagliato, come è documentato

blocchi fino a quando tutte le attività hanno completato l'esecuzione dopo> una richiesta di arresto, o si verifica il timeout, o> thread corrente viene interrotta, se precedente.

Quindi è garantito che entrambe le attività saranno completate o si verificherà un timeout. Il punto è che dobbiamo solo distinguere queste situazioni controllando il valore restituito del metodo awaitTermination. Sarà vero se le attività sono state completate. Falso se timeout o interruzione.

+0

La consistenza della memoria è diversa: vedere https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html – tariksbl

+0

Non correlato in questa situazione. Non ci sono condizioni di competizione tra thread di lavoro e thread dall'esterno del pool in attesa della sua chiusura. – Antoniossss

+1

@ I thread di lavoroAntoniossss e il thread esterno condividono la stessa memoria, come puoi essere sicuro che non ci siano condizioni di gara? Supponiamo che uno degli operai stia scrivendo un valore su un campo statico e che il thread esterno provi a leggerlo dopo che 'awaitTermination' restituisce' true'. Quali sono le garanzie che il thread esterno osserverà che scrive, se succede, prima che non venga applicato? –

Problemi correlati