La parola chiave sincronizzata è ancora utilizzata / necessaria in java?

4

La parola chiave sincronizzata è ancora richiesta (ignora la retrocompatibilità, sto pensando in termini di scrittura di nuovo codice, oggi) o dovremmo utilizzare tutte le funzionalità disponibili nei pacchetti Concurrent e Collection?

    
posta Kevin D 14.04.2011 - 11:56
fonte

4 risposte

5

In effetti è necessario (in situazioni specifiche). Basta leggere attraverso Java Concurrency in Practice , è usato lì molte volte.

Ovviamente, dal momento che Java 5 di solito è in grado di risolvere felicemente i problemi usando (quasi) esclusivamente la toolbox java.util.concurrent . E anche se abbiamo bisogno di scrivere le nostre classi thread-safe, synchronized può spesso essere completamente sostituito da algoritmi non bloccanti come CAS . Tuttavia, CAS ha anche il suo prezzo, in quanto richiede un ragionamento, una sintonizzazione, ecc. Molto preciso e non è ben compreso da molti sviluppatori. Spesso non può fornire alcun vantaggio in termini di prestazioni, ma complica il codice. Quindi ci sono casi in cui è più semplice e più pulito usare solo un blocco synchronized .

Si noti inoltre che i blocchi sono meno costosi di quelli usati in passato, mentre la JVM migliora con ogni versione. Molto tempo fa, questo prezzo è stato quello che ha impedito a molti sviluppatori di utilizzarli, ma non è più così strongmente giustificato (e anche se lo fosse, solo una misura concreta può dimostrare se il collo di bottiglia delle prestazioni è realmente in fase di blocco).

    
risposta data 14.04.2011 - 12:33
fonte
1

L'unico posto in cui synchronized è ancora usato (almeno nel mio codice) scorre su elenchi sincronizzati. Javadocs per Collections.synchronizedCollection dire che ogni volta che viene utilizzato un iteratore, l'intero blocco di codice che utilizza l'iteratore deve essere sincronizzato. Questo perché non stai facendo una singola operazione come add() o remove() , stai facendo più operazioni.

Esempio di codice da Javadocs

Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized(c) {
  Iterator i = c.iterator(); // Must be in the synchronized block
  while (i.hasNext())
     foo(i.next());
}

L'unico modo che conosco per aggirare questa limitazione è quello di accodare tutte le operazioni in un SingleThreadExecutor, ma questa è una soluzione molto costosa e arcaica.

    
risposta data 14.04.2011 - 13:23
fonte
0

Bene, dipende.

In pratica puoi risolvere qualsiasi problema usando i pacchetti simultanei e di raccolta.
Tuttavia, se vieni a scoprire che hai un collo di bottiglia solo nella sincronizzazione, probabilmente dovrai farlo manualmente e la parola chiave sincronizzata potrebbe essere solo l'amico di cui hai bisogno.

Suppongo che questo sia un problema improbabile da affrontare e, di solito, la riprogettazione della responsabilità del thread fornirà una soluzione più pulita rispetto all'ottimizzazione a mano, pur essendo sufficientemente veloce. Non sono riuscito a mettere le mani sulla fonte di quei pacchetti, ma non sarei sorpreso se usassero effettivamente sincronizzati per l'implementazione (ma il contrario non mi sorprenderebbe neanche).

    
risposta data 14.04.2011 - 12:33
fonte
0

Sì, il modificatore sincronizzato è molto vivo e richiesto. Certo, puoi usare Locks e altre cose dal pacchetto java.util.concurrent , ma in molti casi questo è semplicemente un grosso overhead. Se si desidera assicurarsi che un determinato pezzo di codice venga eseguito esclusivamente, la parola chiave sincronizzata è il soluto più rapido e sicuro. Ci sono molte situazioni in cui ottenere un lucchetto, ottenerlo e rilasciarlo semplicemente non è necessario.

Quindi sì, per un buon programma multithread è effettivamente necessario l'uso della parola chiave sincronizzata.

    
risposta data 14.04.2011 - 14:11
fonte

Leggi altre domande sui tag