Domanda

Ho imparato che ogni codice di classe byte è stato caricato nella memoria una volta per ogni caricatore di classe, quindi quando un thread è in esecuzione il codice di byte di un metodo, e un altro thread arriva?

1 filo -> 1 istanza -. della classe Foo == nessun problema

X le discussioni -> 1 istanza - della classe Foo == bisogno di essere gestito questo è chiaro .

X threads -> X rispettivi le istanze - della classe Foo == ??? ?

dovrei assicurarsi che nulla è incasinato nel metodo? se il metodo utilizza un istanza variabili di livello, posso essere sicuro che userà quelle giuste?

Aggiornamento:

vedo la mia domanda non era chiaro per alcuni, ecco un esempio con i numeri

Ho un oggetto di tipo di classe Foo , che non ha la sincronizzazione !!

Ho 5 istanze del Foo con 5 fili corsa per / in ciascuno di essi, e l'accesso esempio parametri di livello per esempio:

class FOO {
     private SomeObject someObject=new SomeObject();

     private void problematicMethod(Data data) {
         someObject.doSomethingWithTheData(data);
         data.doSomethingWithSomeObject(someObject); 
// any way you want it use the data or export the data
     }
}

sto chiedendo c'è un problema qui, poiché non v'è solo 1 byte di codice di questa classe e 5 le istanze di questo oggetto che il codice di accesso questo byte, in modo se voglio impedire loro di sovrapposizione sullo stesso codice di byte, che cosa devo fare?

Grazie, Adamo.

È stato utile?

Soluzione

  

Ho imparato che ogni codice di classe byte è stato caricato nella memoria una volta per ogni caricatore di classe, quindi quando un thread è in esecuzione il codice di byte di un metodo, e un altro thread arriva?

Classe codice di carico e byte è irrilevante in questa sede. bytecode è un insieme di catena di montaggio, come le istruzioni che le interpreta ed elabora JVM in codice macchina nativo. Più di un filo può tranquillamente seguire serie di istruzioni codificate nel codice byte.

  

1 thread -> 1 istanza - di classe Test, nessun problema

Per lo più corretta. Se c'è solo un singolo thread, quindi non c'è alcuna necessità immediata di rendere thread-safe nulla. Tuttavia, ignorando sicurezza filo limiterebbe la crescita e riutilizzo.

  

X discussioni -> 1 istanza -. Di prova di classe, devono essere maneggiati questo è chiaro

Ebbene, sì, per ragioni di visibilità filo e per assicurare che le regioni critiche sono eseguiti atomicamente, utilizzando tecniche di sincronizzazione o di bloccaggio è abbastanza importante. Naturalmente, tutto dipende giusto ?! Se la classe non ha lo stato (istanza o di classe variabili), allora non ha realmente bisogno di rendere thread-safe (si pensi classe di utilità come Executors di Java, Arrays, classi Collections).

  

X discussioni -> X rispettivi casi - della classe Test, ????

Se ogni thread ha la propria istanza della classe Test, e nessuna singola istanza è condivisa tra più di un thread, allora questo è lo stesso del primo esempio. Se un'istanza di test fa riferimento a due o più thread, allora questo è lo stesso del vostro secondo esempio.

  

Se il metodo utilizza un variabili a livello di classe, posso essere sicuro che userà quelle giuste?

variabili di classe sono variabili static in Java. Ci sono già due risposte postato che sottolineano l'importanza di utilizzare synchronized per evitare che più di un thread di modificare una variabile di classe allo stesso tempo. Non menzionato è l'importanza di utilizzare synchronized o volatile per assicurarsi che non si vede una versione non aggiornata del variabile di classe.

Altri suggerimenti

È necessario sincronizzare la risorsa condivisa. Se questa risorsa è un campo a livello di classe, si dovrebbe sincronizzare sulla classe stessa:

public class Foo {
  private static int someNumber = 0;
  // not thread safe
  public void inc_unsafe()  { 
    someNumber++;
  }

  // not thread safe either; we are sync'ing here on an INSTANCE of
  // the Foo class
  public synchronized void inc_also_unsafe()  { 
    someNumber++;
  }

  // here we are safe, because for static methods, synchronized will use the class
  // itself
  public static synchronized void inc_safe()  { 
    someNumber++;
  }

  // also safe, since we use the class itself
  public static synchronized void inc_also_safe()  { 
    synchronized (Foo.class) {
      someNumber++;
    }
  }
}

Si noti che {{}} java.util.concurrent fornisce molti altri modi per dati condivisi protetti rispetto a {{}} sincronizzato parola chiave di Java. Guardare dentro, come potrebbe essere quello che vuoi.

( Per chiunque voglia sostenere che int incremento viene già thread-safe, si prega di notare che questo è solo un esempio e il concetto di base può essere applicato a qualsiasi cosa. )

In aggiunta a di Dave , se si dispone di metodi statici più che il lavoro su diversi membri statici, è meglio per sincronizzare su oggetti statici separati.

public class Foo {
  private static int someNumber = 0;
  private static int otherNumber = 0;
  private static final Object lock1 = new Object();
  private static final Object lock2 = new Object();

  public static void incSomeNumber() {
    synchronized (lock1) {
      someNumber++;
    }
  }

  public static void incOtherNumber() {
    synchronized (lock2) {
      otherNumber++;
    }
  }
}

In questo modo, due diversi thread può chiamare incSomeNumber e incOtherNumber allo stesso tempo, senza rimanere bloccati sulla sincronizzazione.


Modifica

Ecco lo stesso esempio con AtomicInterger. Si noti che non è necessario alcun blocco esplicito. Tutte le operazioni di AtomicIntergers sono atomiche e implementate utilizzando le operazioni di hardware. Così si traducono in migliori prestazioni.

import java.util.concurrent.atomic.AtomicInteger;

public class Foo {
  private static AtomicInteger someNumber = new AtomicInteger(0);
  private static AtomicInteger otherNumber = new AtomicInteger(0);

  public static int incSomeNumber() {
    return someNumber.incrementAndGet();
  }

  public static int incOtherNumber() {
    return otherNumber.incrementAndGet();
  }
}

Tutte le discussioni dovrebbero andare alla stessa classe Loader. 10 fili utilizzando FOo.class, tutti 10 avranno lo stesso oggetto esatto. L'unico modo si otterrebbe la stessa classe in diverse classloader sarebbe se

a) Hai scritto il tuo codice che ha fatto la magia di classe Loader b) Hai fatto qualcosa di strano come includere il codice sia all'interno di una guerra, e all'interno di una condivisa Tomcat cartella lib ... e ha fatto la giusta sequenza di eventi per causare 2 copie da caricare da luoghi diversi.

In tutti i casi normali .. fate una classe, c'è esattamente 1 copia dell'oggetto di classe, e tutto sincronizzazione (questo) sarà in tutta l'intera applicazione.

E penso, variabile di istanza come variabile locale è unico per ogni thread. Così per impostazione predefinita è filo safe.But sì, è ancora necessaria per essere curato da Sincronizzazione .

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