Domanda

Sono veramente nuovo a Java e ho letto che synchronized è "molto costoso" in Java. Tutto quello che voglio sapere è ciò che è costoso e come è costoso?

Grazie.

È stato utile?

Soluzione

Forse non è così male come si pensa

E 'usato per essere terribile (che è forse il motivo per cui si legge che era "molto costoso"). Questi memi possono richiedere molto tempo a morire

  

Come costoso è la sincronizzazione?

     

A causa delle regole che coinvolgono cache di lavaggio e invalidazione, un blocco sincronizzato nel linguaggio Java è generalmente più costoso rispetto ai servizi sezione critica offerti da molte piattaforme, che sono di solito realizzate con una atomica "di prova e impostare il bit" istruzione macchina. Anche quando un programma contiene un solo filo in esecuzione su un singolo processore, una chiamata metodo sincronizzato è ancora più lento di una chiamata di metodo non-sincronizzato. Se la sincronizzazione effettivamente richiede contendono la serratura, la penalizzazione delle prestazioni è sostanzialmente maggiore, come ci saranno diversi interruttori discussione e chiamate di sistema necessarie.

     

Fortunatamente, continui miglioramenti JVM hanno entrambe migliorate prestazioni complessive programma Java e ridotto il costo relativo di sincronizzazione con ogni release, e futuri miglioramenti sono attesi. Inoltre, i costi delle prestazioni di sincronizzazione sono spesso esagerati. Una fonte noto ha citato che una chiamata al metodo sincronizzato è fino a 50 volte più lento di una chiamata di metodo non-sincronizzato. Anche se questa affermazione può essere vero, ma è anche abbastanza fuorviante e ha portato molti sviluppatori per evitare la sincronizzazione, anche nei casi in cui è necessario.

Detto questo - programmazione concorrente può ancora essere lento, ma non così gran parte di essa è puramente colpa di Java ora. V'è un compromesso tra fine e bloccaggio grossolani. Troppo grossolana è ovviamente male, ma è possibile essere troppo troppo fine, come serrature hanno un costo non nullo.

E 'importante considerare la particolare risorsa in contesa. dischi rigidi meccanici sono un esempio in cui più thread possono portare a peggio prestazioni.

Altri suggerimenti

E 'costoso, perché se si sta utilizzando fili, e un certo numero di fili devono passare attraverso una sezione di codice sincronizzato, solo uno di essi può essere eseguito in un momento.

E 'come un collo di bottiglia.

E 'anche costoso quando si utilizza un singolo thread, perché deve controllare in ogni caso se è consentita l'esecuzione.

Se si riduce l'uso di segmenti sincronizzati tuo thread non dovrà fermarsi per vedere se possono funzionare (ovviamente, non hanno di condividere i dati)

Una panoramica di alto livello su come si possono trovare opere di sincronizzazione qui

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

Un monitor stile Java

Questo non è quello specifico per Java. La sincronizzazione può essere considerato "costoso" in qualsiasi ambiente multi-thread se non eseguite correttamente. Che si tratti di particolarmente grave in Java, non lo so.

Impedisce thread di esecuzione contemporaneamente se usano la stessa risorsa. Ma, dal momento che do usare la stessa risorsa, non c'è scelta migliore (che deve essere fatto).

Il problema è che le persone spesso proteggere una risorsa con troppo grande una portata. Ad esempio, un programma mal progettato può sincronizzare un intero array di oggetti piuttosto che ogni singolo elemento dell'array (o anche una sezione della matrice).

Ciò significa che un thread cercando di leggere elemento 7 deve attendere una lettura filo o elemento 22. Non è necessario scrivere. Se la granularità della sincronizzazione erano al livello elemento anziché livello di matrice, i due fili non sarebbero interferire con l'altro.

Solo quando due thread tentato di accedere al stesso elemento ci sarebbe risorsa contesa. È per questo che la regola generale è quella di proteggere solo come piccola risorsa possibile (fatte salve le limitazioni sul numero di sincronizzazioni, ovviamente).

Ma, ad essere onesti, non importa quanto è caro se l'alternativa è la corruzione di dati a causa di due thread in lotta per una singola risorsa. Scrivere l'applicazione in modo corretto e solo preoccuparsi di problemi di prestazioni se e quando appaiono ( "Get it lavorando prima poi farlo funzionare veloce" è un mantra dei miei preferiti).

sopra a IBM riassume in realtà molto bene i punti principali dietro la sincronizzazione.

  

A causa delle regole che coinvolgono cache di lavaggio e invalidazione, un blocco sincronizzato nel linguaggio Java è generalmente più costoso rispetto ai servizi sezione critica offerti da molte piattaforme, che sono di solito realizzate con una atomica "di prova e impostare il bit" istruzione macchina. Anche quando un programma contiene un solo filo in esecuzione su un singolo processore, una chiamata metodo sincronizzato è ancora più lento di una chiamata di metodo non sincronizzato. Se la sincronizzazione effettivamente richiede contendono la serratura, la penalizzazione delle prestazioni è sostanzialmente maggiore, come ci saranno diversi interruttori discussione e chiamate di sistema necessarie.

Le altre risposte danno un buon livello di dettaglio tecnico che io non ho intenzione di tentare di replicare.

Quello che farò è vi consiglio di controllare le date degli articoli (così come la competenza e la consapevolezza implicita dell'autore). La sincronizzazione in Java è stato molto lento in JVM precedenti. Tuttavia, è migliorato molto di recente, in modo che la sincronizzazione uncontended è molto più veloce di quanto si possa pensare, e la sincronizzazione uncontended ha migliorato anche.

Intendiamoci, questa domanda forse non importa - se è necessario sincronizzare per garantire la correttezza, la necessità per sincronizzare per garantire la correttezza. Le uniche volte che possono vedere la velocità essendo un problema è se si stavano prendendo in considerazione la creazione di un'implementazione lockless invece (utilizzando il complesso ancora java.util.concurrent.locks.AbstractQueuedSynchronizer ), o forse considerare l'uso di una lingua diversa per il vostro compito, invece.

In generale credo che la migliore conclusione è che la sincronizzazione è in genere sufficiente per l'uso su una prima iterazione. Come per tutti i problemi di prestazioni, il codice per la chiarezza e correttezza in un primo momento e poi ottimizzare solo ciò che si misura da una parte costosa della vostra applicazione. In genere, questo non sarà il costo della sincronizzazione *.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top