C’è un vantaggio nell’usare un metodo sincronizzato invece di un blocco sincronizzato?

Qualcuno può dirmi il vantaggio del metodo sincronizzato sul blocco sincronizzato con un esempio?

Qualcuno può dirmi il vantaggio del metodo sincronizzato sul blocco sincronizzato con un esempio? Grazie.

Non c’è un chiaro vantaggio nell’usare il metodo sincronizzato sul blocco.

Forse l’unico (ma non lo definirei un vantaggio) è che non è necessario includere l’object come riferimento.

Metodo:

 public synchronized void method() { // blocks "this" from here.... ... ... ... } // to here 

Bloccare:

 public void method() { synchronized( this ) { // blocks "this" from here .... .... .... .... } // to here... } 

Vedere? Nessun vantaggio.

I blocchi hanno però dei vantaggi rispetto ai metodi, soprattutto per quanto riguarda la flessibilità poiché è ansible utilizzare un altro object come blocco, mentre la sincronizzazione del metodo bloccherebbe l’intero object.

Confrontare:

 // locks the whole object ... private synchronized void someInputRelatedWork() { ... } private synchronized void someOutputRelatedWork() { ... } 

vs.

 // Using specific locks Object inputLock = new Object(); Object outputLock = new Object(); private void someInputRelatedWork() { synchronized(inputLock) { ... } } private void someOutputRelatedWork() { synchronized(outputLock) { ... } } 

Inoltre, se il metodo cresce, puoi comunque mantenere separata la sezione sincronizzata:

  private void method() { ... code here ... code here ... code here synchronized( lock ) { ... very few lines of code here } ... code here ... code here ... code here ... code here } 

L’unica vera differenza è che un blocco sincronizzato può scegliere su quale object si sincronizza. Un metodo sincronizzato può utilizzare solo 'this' (o l’istanza Class corrispondente per un metodo di class sincronizzato). Ad esempio, questi sono semanticamente equivalenti:

 synchronized void foo() { ... } void foo() { synchronized (this) { ... } } 

Quest’ultimo è più flessibile in quanto può competere per il blocco associato di qualsiasi object, spesso una variabile membro. È anche più granulare perché potresti eseguire codice simultaneo in esecuzione prima e dopo il blocco, ma sempre all’interno del metodo. Naturalmente, si potrebbe facilmente usare un metodo sincronizzato rifasando il codice concorrente in metodi separati non sincronizzati. Utilizzare ciò che rende il codice più comprensibile.

Metodo sincronizzato

Professionisti:

  • Il tuo IDE può indicare i metodi sincronizzati.
  • La syntax è più compatta.
  • Forza la divisione dei blocchi sincronizzati in metodi separati.

Contro:

  • Si sincronizza con questo e quindi rende ansible agli estranei di sincronizzarsi anche con esso.
  • È più difficile spostare il codice all’esterno del blocco sincronizzato.

Blocco sincronizzato

Professionisti:

  • Consente di utilizzare una variabile privata per il blocco e quindi forzare il blocco a rimanere all’interno della class.
  • I blocchi sincronizzati possono essere trovati cercando i riferimenti alla variabile.

Contro:

  • La syntax è più complicata e quindi rende il codice più difficile da leggere.

Personalmente preferisco usare metodi sincronizzati con classi focalizzate solo sulla cosa che necessita di sincronizzazione. Tale class dovrebbe essere il più piccola ansible e quindi dovrebbe essere facile rivedere la sincronizzazione. Gli altri non dovrebbero preoccuparsi della sincronizzazione.

La differenza principale è che se si utilizza un blocco sincronizzato è ansible bloccare un object diverso da quello che consente di essere molto più flessibile.

Supponi di avere una coda di messaggi e più produttori e consumatori di messaggi. Non vogliamo che i produttori interferiscano l’uno con l’altro, ma i consumatori dovrebbero essere in grado di recuperare i messaggi senza dover attendere i produttori. Quindi creiamo solo un object

 Object writeLock = new Object(); 

E da ora in poi ogni volta che un produttore vuole aggiungere un nuovo messaggio ci limitiamo a questo:

 synchronized(writeLock){ // do something } 

Quindi i consumatori possono ancora leggere e i produttori saranno bloccati.

Metodo sincronizzato

I metodi sincronizzati hanno due effetti.
Innanzitutto, quando un thread sta eseguendo un metodo sincronizzato per un object, tutti gli altri thread che invocano metodi sincronizzati per lo stesso blocco object (sospendi l’esecuzione) finché il primo thread non viene eseguito con l’object.

In secondo luogo, quando un metodo sincronizzato si chiude, stabilisce automaticamente una relazione prima-accade con qualsiasi successiva chiamata di un metodo sincronizzato per lo stesso object. Ciò garantisce che le modifiche allo stato dell’object siano visibili a tutti i thread.

Nota che i costruttori non possono essere sincronizzati – l’uso della parola chiave sincronizzata con un costruttore è un errore di syntax. La sincronizzazione dei costruttori non ha senso, perché solo il thread che crea un object dovrebbe avere accesso ad esso mentre viene costruito.

Dichiarazione sincronizzata

A differenza dei metodi sincronizzati, le istruzioni sincronizzate devono specificare l’object che fornisce il blocco intrinseco: molto spesso lo uso per sincronizzare l’accesso a un elenco o una mappa, ma non voglio bloccare l’accesso a tutti i metodi dell’object.

Q: Serrature intrinseche e sincronizzazione La sincronizzazione è costruita attorno a un’ quadro interna nota come blocco intrinseco o blocco del monitor. (Le specifiche API spesso si riferiscono a questa entity framework semplicemente come un “monitor”.) I blocchi intrinseci svolgono un ruolo in entrambi gli aspetti della sincronizzazione: rafforzano l’accesso esclusivo allo stato di un object e stabiliscono le relazioni prima-accade che sono essenziali per la visibilità.

Ad ogni object è associato un blocco intrinseco. Per convenzione, un thread che richiede un accesso esclusivo e coerente ai campi di un object deve acquisire il blocco intrinseco dell’object prima di accedervi e quindi rilasciare il blocco intrinseco quando viene eseguito con essi. Si dice che un filo possiede il blocco intrinseco tra il tempo in cui ha acquisito il blocco e ha rilasciato il blocco. Finché un thread possiede un blocco intrinseco, nessun altro thread può acquisire lo stesso blocco. L’altro thread si bloccherà quando tenta di acquisire il blocco.

 package test; public class SynchTest implements Runnable { private int c = 0; public static void main(String[] args) { new SynchTest().test(); } public void test() { // Create the object with the run() method Runnable runnable = new SynchTest(); Runnable runnable2 = new SynchTest(); // Create the thread supplying it with the runnable object Thread thread = new Thread(runnable,"thread-1"); Thread thread2 = new Thread(runnable,"thread-2"); // Here the key point is passing same object, if you pass runnable2 for thread2, // then its not applicable for synchronization test and that wont give expected // output Synchronization method means "it is not possible for two invocations // of synchronized methods on the same object to interleave" // Start the thread thread.start(); thread2.start(); } public synchronized void increment() { System.out.println("Begin thread " + Thread.currentThread().getName()); System.out.println(this.hashCode() + "Value of C = " + c); // If we uncomment this for synchronized block, then the result would be different // synchronized(this) { for (int i = 0; i < 9999999; i++) { c += i; } // } System.out.println("End thread " + Thread.currentThread().getName()); } // public synchronized void decrement() { // System.out.println("Decrement " + Thread.currentThread().getName()); // } public int value() { return c; } @Override public void run() { this.increment(); } } 

Controllo incrociato di uscite diverse con metodo sincronizzato, blocco e senza sincronizzazione.

Nota: i metodi ei blocchi sincronizzati statici funzionano sull’object Class.

 public class MyClass { // locks MyClass.class public static synchronized void foo() { // do something } // similar public static void foo() { synchronized(MyClass.class) { // do something } } } 

Quando il compilatore java converte il codice sorgente in codice byte, gestisce i metodi sincronizzati e i blocchi sincronizzati in modo molto diverso.

Quando JVM esegue un metodo sincronizzato, il thread in esecuzione identifica che la struttura method_info del metodo ha il flag ACC_SYNCHRONIZED impostato, quindi acquisisce automaticamente il blocco dell’object, chiama il metodo e rilascia il blocco. Se si verifica un’eccezione, il thread rilascia automaticamente il blocco.

La sincronizzazione di un blocco metodo, d’altro canto, ignora il supporto integrato della JVM per l’acquisizione del blocco di un object e la gestione delle eccezioni e richiede che la funzionalità venga scritta in modo esplicito nel codice byte. Se si legge il codice byte per un metodo con un blocco sincronizzato, verranno visualizzate più di una dozzina di operazioni aggiuntive per gestire questa funzionalità.

Mostra le chiamate per generare sia un metodo sincronizzato che un blocco sincronizzato:

 public class SynchronizationExample { private int i; public synchronized int synchronizedMethodGet() { return i; } public int synchronizedBlockGet() { synchronized( this ) { return i; } } } 

Il metodo synchronizedMethodGet() genera il seguente codice byte:

 0: aload_0 1: getfield 2: nop 3: iconst_m1 4: ireturn 

Ed ecco il codice byte dal metodo synchronizedBlockGet() :

 0: aload_0 1: dup 2: astore_1 3: monitorenter 4: aload_0 5: getfield 6: nop 7: iconst_m1 8: aload_1 9: monitorexit 10: ireturn 11: astore_2 12: aload_1 13: monitorexit 14: aload_2 15: athrow 

Una differenza significativa tra metodo sincronizzato e blocco è che, il blocco sincronizzato generalmente riduce l’ambito del blocco. Poiché l’ambito della serratura è inversamente proporzionale alle prestazioni, è sempre meglio bloccare solo la parte critica del codice. Uno dei migliori esempi di utilizzo del blocco sincronizzato è il doppio controllo del blocco nel modello Singleton, dove invece di bloccare l’intero metodo getInstance() , si blocca solo la sezione critica del codice utilizzata per creare l’istanza Singleton. Ciò migliora drasticamente le prestazioni poiché il blocco è richiesto solo una o due volte.

Quando si utilizzano metodi sincronizzati, sarà necessario prestare particolare attenzione se si mescolano entrambi i metodi sincronizzati statici e sincronizzati non statici.

Molto spesso lo uso per sincronizzare l’accesso a una lista o mappa ma non voglio bloccare l’accesso a tutti i metodi dell’object.

Nel codice seguente un thread che modifica l’elenco non bloccherà in attesa di un thread che sta modificando la mappa. Se i metodi fossero sincronizzati sull’object, allora ogni metodo avrebbe dovuto aspettare anche se le modifiche che stavano apportando non sarebbero in conflitto.

 private List myList = new ArrayList(); private Map(); public void put( String s, Bar b ) { synchronized( myMap ) { myMap.put( s,b ); // then some thing that may take a while like a database access or RPC or notifying listeners } } public void hasKey( String s, ) { synchronized( myMap ) { myMap.hasKey( s ); } } public void add( Foo f ) { synchronized( myList ) { myList.add( f ); // then some thing that may take a while like a database access or RPC or notifying listeners } } public Thing getMedianFoo() { Foo med = null; synchronized( myList ) { Collections.sort(myList); med = myList.get(myList.size()/2); } return med; } 

Con i blocchi sincronizzati, è ansible avere più sincronizzatori, in modo che più cose simultanee ma non conflittuali possano andare avanti allo stesso tempo.

I metodi sincronizzati possono essere controllati utilizzando l’API di reflection. Questo può essere utile per testare alcuni contratti, come tutti i metodi nel modello sono sincronizzati .

Il seguente frammento stampa tutti i metodi sincronizzati di Hashtable:

 for (Method m : Hashtable.class.getMethods()) { if (Modifier.isSynchronized(m.getModifiers())) { System.out.println(m); } } 

Nota importante sull’uso del blocco sincronizzato: attenzione a ciò che si usa come object di blocco!

Il frammento di codice da user2277816 sopra illustra questo punto in quanto un riferimento a una stringa letterale viene usato come object di blocco. Renditi conto che i letterali stringa sono automaticamente internati in Java e dovresti iniziare a vedere il problema: ogni pezzo di codice che si sincronizza sul letterale “blocco”, condivide lo stesso blocco! Questo può facilmente portare a deadlock con pezzi di codice completamente indipendenti.

Non sono solo gli oggetti String a cui devi stare attento. Anche i primitivi in ​​scatola sono un pericolo, poiché il selfboxing ei metodi valueOf possono riutilizzare gli stessi oggetti, a seconda del valore.

Per ulteriori informazioni consultare: https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused

Spesso usare un blocco su un livello di metodo è troppo maleducato. Perché bloccare un pezzo di codice che non accede ad alcuna risorsa condivisa bloccando un intero metodo. Poiché ogni object ha un blocco, è ansible creare oggetti fittizi per implementare la sincronizzazione a livello di blocco. Il livello di blocco è più efficiente perché non blocca l’intero metodo.

Ecco alcuni esempi

Livello del metodo

 class MethodLevel { //shared among threads SharedResource x, y ; public void synchronized method1() { //multiple threads can't access } public void synchronized method2() { //multiple threads can't access } public void method3() { //not synchronized //multiple threads can access } } 

Livello di blocco

 class BlockLevel { //shared among threads SharedResource x, y ; //dummy objects for locking Object xLock = new Object(); Object yLock = new Object(); public void method1() { synchronized(xLock){ //access x here. thread safe } //do something here but don't use SharedResource x, y // because will not be thread-safe synchronized(xLock) { synchronized(yLock) { //access x,y here. thread safe } } //do something here but don't use SharedResource x, y //because will not be thread-safe }//end of method1 } 

[Modificare]

Per Collection like Vector e Hashtable sono sincronizzati quando ArrayList o HashMap non lo sono e devi impostare una parola chiave sincronizzata o invocare il metodo sincronizzato Collections:

 Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map List myList = Collections.synchronizedList (myList); // single lock for the entire list 

Il metodo sincronizzato viene utilizzato per bloccare tutti gli oggetti Il blocco sincronizzato viene utilizzato per bloccare un object specifico

L’unica differenza: i blocchi sincronizzati consentono il blocco granulare a differenza del metodo sincronizzato

Un blocco o metodi sostanzialmente synchronized sono stati utilizzati per scrivere codice thread-safe evitando errori di inconsistenza della memoria.

Questa domanda è molto vecchia e molte cose sono state cambiate negli ultimi 7 anni. Nuovi costrutti di programmazione sono stati introdotti per la sicurezza delle filettature.

È ansible ottenere la sicurezza del thread utilizzando l’API di concorrenza avanzata anziché synchronied blocchi synchronied . Questa pagina di documentazione fornisce buoni costrutti di programmazione per ottenere la sicurezza del thread.

Gli oggetti di blocco supportano idiomi di blocco che semplificano molte applicazioni concorrenti.

Gli esecutori definiscono un’API di alto livello per l’avvio e la gestione dei thread. Le implementazioni dell’esecutore fornite da java.util.concurrent forniscono la gestione del pool di thread adatta per applicazioni su larga scala.

Le raccolte simultanee semplificano la gestione di ampie raccolte di dati e possono ridurre notevolmente la necessità di sincronizzazione.

Le variabili atomiche hanno caratteristiche che riducono al minimo la sincronizzazione e aiutano a evitare errori di coerenza della memoria.

ThreadLocalRandom (in JDK 7) fornisce una generazione efficiente di numeri pseudocasuali da più thread.

La sostituzione migliore per la sincronizzazione è ReentrantLock , che utilizza l’API di Lock

Un’esclusione reciproca rientrante Blocca con lo stesso comportamento di base e la semantica del blocco del monitor implicito a cui si accede utilizzando i metodi e le istruzioni sincronizzati, ma con funzionalità estese.

Esempio con serrature:

 class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } } 

Fare riferimento ai pacchetti java.util.concurrent e java.util.concurrent.atomic anche per altri costrutti di programmazione.

Fai riferimento anche a questa domanda correlata:

Sincronizzazione vs blocco

In generale questi sono per lo più gli stessi oltre ad essere espliciti sul monitor dell’object che viene usato rispetto all’implicito questo object. Uno svantaggio di metodi sincronizzati, a mio avviso a volte trascurato, è che l’uso del riferimento “this” per sincronizzare su di te lascia aperta la possibilità di bloccare oggetti esterni sullo stesso object. Questo può essere un insetto molto sottile se ci si imbatte in esso. La sincronizzazione su un object esplicito interno o su un altro campo esistente può evitare questo problema, incapsulando completamente la sincronizzazione.

Come già detto qui, il blocco sincronizzato può utilizzare la variabile definita dall’utente come object di blocco, quando la funzione sincronizzata utilizza solo “questo”. E naturalmente puoi manipolare le aree della tua funzione che dovrebbero essere sincronizzate. Ma tutti dicono che nessuna differenza tra funzione sincronizzata e blocco copre l’intera funzione usando “questo” come object di blocco. Questo non è vero, la differenza è nel codice byte che verrà generato in entrambe le situazioni. In caso di blocco sincronizzato, si deve assegnare una variabile locale che mantenga il riferimento a “questo”. E come risultato avremo una dimensione un po ‘più grande per la funzione (non rilevante se hai solo un numero limitato di funzioni).

Spiegazione più dettagliata della differenza che puoi trovare qui: http://www.artima.com/insidejvm/ed2/threadsynchP.html

In caso di metodi sincronizzati, il blocco verrà acquisito su un object. Ma se vai con blocco sincronizzato hai la possibilità di specificare un object su cui il blocco sarà acquisito.

Esempio :

  Class Example { String test = "abc"; // lock will be acquired on String test object. synchronized (test) { // do something } lock will be acquired on Example Object public synchronized void testMethod() { // do some thing } } 

So che questa è una vecchia domanda, ma con la mia rapida lettura delle risposte qui, non ho visto nessuno menzionare che a volte un metodo synchronized potrebbe essere il blocco sbagliato .
Da Java Concurrency In Practice (pagina 72):

 public class ListHelper { public List list = Collections.syncrhonizedList(new ArrayList<>()); ... public syncrhonized boolean putIfAbsent(E x) { boolean absent = !list.contains(x); if(absent) { list.add(x); } return absent; } 

Il codice precedente ha l’ aspetto di essere thread-safe. Tuttavia, in realtà non lo è. In questo caso il blocco si ottiene sull’istanza della class. Tuttavia, è ansible che l’ elenco venga modificato da un altro thread che non utilizza tale metodo. L’approccio corretto sarebbe da usare

 public boolean putIfAbsent(E x) { synchronized(list) { boolean absent = !list.contains(x); if(absent) { list.add(x); } return absent; } } 

Il codice precedente bloccherebbe tutti i thread cercando di modificare l’ elenco dalla modifica dell’elenco fino al completamento del blocco sincronizzato.

In pratica, il vantaggio dei metodi sincronizzati rispetto ai blocchi sincronizzati è che sono più resistenti agli idioti; poiché non è ansible scegliere un object arbitrario da bloccare, non è ansible utilizzare in modo improprio la syntax del metodo sincronizzato per fare cose stupide come il blocco su una stringa letterale o il blocco dei contenuti di un campo mutabile che viene modificato da sotto i thread.

D’altra parte, con i metodi sincronizzati non è ansible proteggere il blocco dall’acquisizione da parte di alcun thread che può ottenere un riferimento all’object.

Pertanto, l’uso sincronizzato come modificatore dei metodi è più efficace nel proteggere i propri cow-cow dal farsi del male, mentre l’uso di blocchi sincronizzati in combinazione con gli oggetti lock finali privati ​​è più efficace per proteggere il proprio codice dai cow-orkers.

Da un riepilogo delle specifiche Java: http://www.cs.cornell.edu/andru/javaspec/17.doc.html

L’istruzione sincronizzata (§14.17) calcola un riferimento a un object; quindi tenta di eseguire un’azione di blocco su quell’object e non procede ulteriormente finché l’azione di blocco non è stata completata correttamente. …

Un metodo sincronizzato (§8.4.3.5) esegue automaticamente un’azione di blocco quando viene richiamato; il suo corpo non viene eseguito fino a quando l’azione di blocco non è stata completata correttamente. Se il metodo è un metodo di istanza , blocca il blocco associato all’istanza per cui è stato richiamato (ovvero, l’object che sarà noto come questo durante l’esecuzione del corpo del metodo). Se il metodo è statico , blocca il blocco associato all’object Class che rappresenta la class in cui è definito il metodo. …

Sulla base di queste descrizioni, direi che la maggior parte delle risposte precedenti sono corrette, e un metodo sincronizzato potrebbe essere particolarmente utile per i metodi statici, dove altrimenti dovresti capire come ottenere l’object “Class che rappresenta la class in cui il metodo è stato definito.”

Edit: Inizialmente pensavo che fossero citazioni dell’attuale specifica Java. Chiarito che questa pagina è solo un riassunto / spiegazione delle specifiche

TLDR; Non utilizzare il modificatore synchronized né l’espressione synchronized(this){...} ma synchronized(myLock){...} dove myLock è un campo di istanza finale che contiene un object privato.


La differenza tra l’utilizzo del modificatore synchronized sulla dichiarazione del metodo e l’espressione synchronized(..){ } nel corpo del metodo sono le seguenti:

  • Il modificatore synchronized specificato sulla firma del metodo
    1. è visibile nel JavaDoc generato,
    2. è programmabile tramite riflessione durante la verifica del modificatore di un metodo per Modifier.SYNCHRONIZED ,
    3. richiede meno tipizzazione e indention rispetto a synchronized(this) { .... } , e
    4. (a seconda dell’IDE) è visibile nello schema della class e nel completamento del codice,
    5. usa this object come lock quando viene dichiarato su un metodo non statico o sulla class che lo include quando viene dichiarato su un metodo statico.
  • L’espressione synchronized(...){...} ti consente
    1. sincronizzare solo l’esecuzione di parti del corpo di un metodo,
    2. da utilizzare all’interno di un costruttore o di un blocco di inizializzazione ( statico ),
    3. per scegliere l’object di blocco che controlla l’accesso sincronizzato.

Tuttavia, usando il modificatore synchronized o synchronized(...) {...} con this come object di blocco (come in synchronized(this) {...} ), si ha lo stesso svantaggio. Entrambi utilizzano la propria istanza come object di blocco su cui eseguire la sincronizzazione. Questo è pericoloso perché non solo l’object stesso ma qualsiasi altro object / codice esterno che contiene un riferimento a quell’object può anche usarlo come un blocco di sincronizzazione con effetti collaterali potenzialmente gravi (degrado delle prestazioni e deadlock ).

Pertanto, la best practice è di non utilizzare né il modificatore synchronized né l’espressione synchronized(...) insieme a this come object di blocco ma un object di blocco riservato a questo object. Per esempio:

 public class MyService { private final lock = new Object(); public void doThis() { synchronized(lock) { // do code that requires synchronous execution } } public void doThat() { synchronized(lock) { // do code that requires synchronous execution } } } 

È inoltre ansible utilizzare più oggetti di blocco, ma è necessario prestare particolare attenzione per garantire che non si verifichi un deadlock quando utilizzato nidificato.

 public class MyService { private final lock1 = new Object(); private final lock2 = new Object(); public void doThis() { synchronized(lock1) { synchronized(lock2) { // code here is guaranteed not to be executes at the same time // as the synchronized code in doThat() and doMore(). } } public void doThat() { synchronized(lock1) { // code here is guaranteed not to be executes at the same time // as the synchronized code in doThis(). // doMore() may execute concurrently } } public void doMore() { synchronized(lock2) { // code here is guaranteed not to be executes at the same time // as the synchronized code in doThis(). // doThat() may execute concurrently } } } 

Sincronizzazione con i thread. 1) NON usare MAI sincronizzato (questo) in un thread che non funziona. La sincronizzazione con (this) utilizza il thread corrente come object thread di blocco. Poiché ogni thread è indipendente da altri thread, non c’è coordinamento della sincronizzazione. 2) I test di codice mostrano che in Java 1.6 su un Mac la sincronizzazione del metodo non funziona. 3) sincronizzato (lockObj) dove lockObj è un object condiviso comune di tutti i thread che si sincronizzano su di esso funzionerà. 4) ReenterantLock.lock () e .unlock () funzionano. Consulta le esercitazioni Java per questo.

Il seguente codice mostra questi punti. Contiene anche il vettore sicuro per il thread che sarebbe sostituito con ArrayList, per mostrare che molti thread che si aggiungono a un vettore non perdono alcuna informazione, mentre lo stesso con un arraylist può perdere informazioni. 0) Il codice corrente mostra la perdita di informazioni a causa delle condizioni di gara. A) Commenta la linea A etichettata corrente e decommenta la riga A sopra di essa, quindi esegui, il metodo perde i dati ma non dovrebbe. B) Passaggio inverso A, commento B e // blocco finale}. Quindi esegui per vedere i risultati senza perdita di dati C) Commenta B, non commentato C. Esegui, vedi la sincronizzazione su (this) perde i dati, come previsto. Non avere tempo per completare tutte le varianti, spero che questo aiuti. Se la sincronizzazione su (this), o la sincronizzazione del metodo funziona, si prega di indicare quale versione di Java e sistema operativo è stato testato. Grazie.

 import java.util.*; /** RaceCondition - Shows that when multiple threads compete for resources thread one may grab the resource expecting to update a particular area but is removed from the CPU before finishing. Thread one still points to that resource. Then thread two grabs that resource and completes the update. Then thread one gets to complete the update, which over writes thread two's work. DEMO: 1) Run as is - see missing counts from race condition, Run severa times, values change 2) Uncomment "synchronized(countLock){ }" - see counts work Synchronized creates a lock on that block of code, no other threads can execute code within a block that another thread has a lock. 3) Comment ArrayList, unComment Vector - See no loss in collection Vectors work like ArrayList, but Vectors are "Thread Safe" May use this code as long as attribution to the author remains intact. /mf */ public class RaceCondition { private ArrayList raceList = new ArrayList(); // simple add(#) // private Vector raceList = new Vector(); // simple add(#) private String countLock="lock"; // Object use for locking the raceCount private int raceCount = 0; // simple add 1 to this counter private int MAX = 10000; // Do this 10,000 times private int NUM_THREADS = 100; // Create 100 threads public static void main(String [] args) { new RaceCondition(); } public RaceCondition() { ArrayList arT = new ArrayList(); // Create thread objects, add them to an array list for( int i=0; i