2013-04-14 9 views
28

Ho la superclasse Point e un metodo synchronizeddraw(). Le sottoclassi di Point erediteranno synchronized se eseguo l'override del metodo draw() o devo sempre scriverlo?È sincronizzato ereditato in Java?

+0

possibile duplicato di [Override di una sincronizzato metodo] (http://stackoverflow.com/questions/10173345/overriding-a-synchronized-method) – Raedwald

risposta

28

No, sarà sempre necessario scrivere synchronized. Se chiami il metodo sincronizzato della super classe, questa sarà ovviamente una chiamata sincronizzata. synchronized non fa parte della firma del metodo.

Vedere http://gee.cs.oswego.edu/dl/cpj/mechanics.html per la descrizione dettagliata di Doug Lea, capo di threading Java (o così).

+2

Forse chiarire un dettaglio: se una determinata chiamata di metodo è sincronizzata o meno dipende dal tipo dinamico dell'oggetto su cui è chiamato, non dal tipo statico. Cioè, se 'foo()' è 'sincronizzato' in' Derivato' ma non in 'Base', e si assegna un' Derivato' a una variabile 'Base' e ​​si chiama' foo() 'su di esso, quella chiamata sarà essere sincronizzati Questo punto è implicito in 8.4.3.6 delle specifiche del linguaggio (che dice che un metodo 'synchronized' è equivalente a un'istruzione' synchronized' all'interno di quel metodo), ma non riuscivo a trovarlo scritto altrove. Demo eseguibile [qui] (http://runnable.com/U4zBThIj5WNju2g2/). – mrec

4

il metodo Overriden sarà non più sincronizzato se lo si ignora e si rimuove lo synchronized. Trovato here e here

+1

Nessuna delle tue citazioni è un riferimento normativo. – EJP

10

Potete controllare voi stessi scrivendo questo:

public class Shape { 

    protected int sum = 0; 

    public synchronized void add(int x) { 
     sum += x; 
    } 
} 


public class Point extends Shape{ 

    public void add(int x) { 
     sum += x; 
    } 

    public int getSum() { 
     return sum; 
    } 
} 

E prova di classe

public class TestShapes { 

    public final static int ITERATIONS = 100000; 

    public static void main(String[] args) throws InterruptedException { 

     final Point p = new Point(); 

     Thread t1 = new Thread(){ 
      @Override 
      public void run() { 

       for(int i=0; i< ITERATIONS; i++){ 
        p.add(1); 
       } 
      } 
     }; 

     Thread t2 = new Thread(){ 
      @Override 
      public void run() { 

       for(int i=0; i< ITERATIONS; i++){ 
        p.add(1); 
       } 
      } 
     }; 

     t1.start(); 
     t2.start(); 

     t1.join(); 
     t2.join(); 


     System.out.println(p.getSum()); // should equal 200000 

    } 
} 

Sulla mia macchina era 137099 invece di 200000.

+2

il modo più semplice per testare sarebbe testare su ['Thread.holdsLock (this);'] (http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#holdsLock% 28java.lang.Object% 29) nel metodo sottoposto a override –

+4

Non risponde alla domanda. Il codice di test potrebbe semplicemente esporre un bug o un'anomalia temporale dovuta a qualcosa di diverso dalla sincronizzazione. La risposta si trova nelle specifiche del linguaggio. – EJP

+0

@EJP All'inizio ho pensato che ti fossi sbagliato. Poi ho capito che avevi ragione, ma piuttosto pessimista ... – Timo