2013-12-15 3 views
5

Ho una domanda semplice dai dump di OCJP.Depositi OCJP multithreading ThreadSeven extends Thread

DOMANDA NO: 220 Dato:

1. public class TestSeven extends Thread { 
2.  private static int x; 
3.  public synchronized void doThings() { 
4.   int current = x; 
5.   current++; 
6.   x = current; 
7.  } 
8.  public void run() { 
9.   doThings(); 
10. } 
11. } 

Quale affermazione è vera?

A. La compilazione non riesce.

B. Un'eccezione viene generata in fase di esecuzione.

C. La sincronizzazione del metodo run() renderebbe la classe thread-safe.

D. I dati nella variabile "x" sono protetti da problemi di accesso simultaneo.

E. Dichiarare il metodo doThings() come statico renderebbe la classe thread-safe.

F. Il wrapping delle istruzioni all'interno di doThings() in un blocco sincronizzato (nuovo Object()) {} renderebbe la classe thread-safe.

risposta è l'opzione E.

La mia domanda: come doThings() viene già synchornozed, non ne fanno thread-safe?

Si prega di fornire anche alcuni buoni collegamenti per questi argomenti.

risposta

7

Il problema è che x è una variabile statica, che è quindi condivisa da tutti i thread. E poiché tutti i thread non sono sincronizzati su un singolo oggetto (ogni thread usa this come blocco), nulla impedisce a due thread di eseguire il metodo doThings() in parallelo. Due thread potrebbero quindi leggere il valore di x in parallelo e quindi incrementarlo in parallelo, con incrementi mancanti.

Effettuare doThings() statica renderebbe tutti i fili synchonize su un singolo oggetto: TestSeven.class

+0

+1

1

No, perché accede al campo statico x non atomico. È anche possibile renderlo protetto da thread utilizzando java.util.concurrent.atomic.AtomicInteger con getAndIncrement().

Ma la forma originale non è, si consideri un secondo thread che raggiunge la linea 1 mentre un altro thread è sulla linea 3 ... uno degli incrementi andrebbe perso.

3

Un synchronized associato il metodo di un'istanza di un oggetto non si cura di variabili statiche, che sono variabili di classe. Infatti, nel tuo caso, la variabile mutato è una static uno: x

Per sincronizzare una variabile statica, entrambi i modi più semplici in questo frammento di codice sarebbe di dichiarare doThings() come static (in modo che si chiudeva sul classe stessa, non l'oggetto), o per bloccare la TestSeven.class nel caso di un blocco synchronized:

public synchronized static void doThings() 

o

public void doThings(){ 
    synchronized(TestSeven.class){ 
    //... 
    } 
} 
2

No, che metodo doThings() non è thread-safe, perché, è stato sincronizzato su this istanza significa che diversi oggetti useranno loro come blocco per accedervi. Quindi nessuna sincronizzazione è lì. Se il metodo doThings() utilizza un blocco condiviso per accedere al metodo, questo metodo è perfettamente sincronizzato. Oppure, rendendolo sincronizzato la proprietà a livello di classe.