Domanda

Ho una classe Java che viene utilizzata in un'applicazione multithreading.L'accesso simultaneo è molto probabile.Più operazioni di lettura concorrente non dovrebbero bloccare quindi sto usando un blocco di readwrite.

class Example {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private int i;
    private boolean b;

    public int getI() {
      lock.readLock().lock();
      final int tmp = i;
      lock.readLock().unlock(),
      return tmp;
    }

    public void setI( final int i ) {
      lock.writeLock().lock();
      this.i = i;
      lock.writeLock().unlock();
    }

    public boolean getB() {
      lock.readLock().lock();
      final boolean tmp = b;
      lock.readLock().unlock(),
      return tmp;
    }

    public void setB( final boolean b ) {
      lock.writeLock().lock();
      this.b = b;
      lock.writeLock().unlock();
    }
}
.

Per semplicità ho lasciato fuori i blocchi try...finally attorno alle serrature in questo esempio.

Mi chiedo se è necessario (o diciamo raccomandato) per bloccare / sincronizzare getter e setter dei tipi primitivi?So che le operazioni di assegnazione e di ritorno in Java sono atomiche.Tuttavia, utilizzando queste serrature, non posso assicurarmi che ogni accessor riceve l'ultimo valore (uguale a utilizzare volatile)?

Cosa succede se i primitivi fossero double o long?

È stato utile?

Soluzione

dipende.

Nota, tuttavia, che di solito è necessario sincronizzare le operazioni a livello più grossolano, ad esempio, questo:

Example e = ...;

synchronized (e) {
    e.setI(e.getI() + 10);
}
.

Per tali scenari, le tue serrature interne sono ridondanti.Pertanto forse sarebbe meglio applicare la sincronizzazione esterna in cui si utilizzano questi oggetti, piuttosto che la sincronizzazione interna.

Altri suggerimenti

Hai qualcosa come Atomicinteger in Java, che funziona bene con un'applicazione multithread.

Chiediti se questa classe può essere implementata come classe immutabile.Sarà più facile lavorare con e sarà intrinsecamente cassaforte.Non dovrai preoccuparti della concorrenza, delle serrature, della sincronizzazione ecc.

Esempio di una classe immutabile:

final class Example {
    private final int i;
    private final boolean b;

    public Example(int i, boolean b){
        this.i = i ;
        this.b = b;
    }

    public int getI() {
        return i;
    }

    public boolean getB() {
        return b;
    }
}
.

Designirei la tua domanda in modo da non avere accesso simultaneo a un tipo di dati grezzi come questo.L'aggiunta di un blocco di basso livello è probabile che rallenta la tua applicazione così tanto che non vale la pena threading della tua applicazione.

E.G.Diciamo di avere un sistema di 32 core che scale perfettamente e funziona 32x più velocemente rispetto a 1 nucleo.Tuttavia, un accesso al campo senza bloccare richiede 1 NS, con il blocco richiede 1 US (1000 NS) così alla fine la tua applicazione potrebbe richiedere ~ 30x più lento.(1000 più lento / 32 più veloce) Se hai solo 4 core, potrebbe essere centinaia di volte più lento, sconfiggendo lo scopo di avere multi-thread in primo luogo.IMHO.

Non è necessario bloccare / sincronizzare Getters e Setter dei tipi primitivi - Tagging come volatile è sufficiente nella maggior parte dei casi (a parte il doppio e lungo come citini)

Poiché uno dei post precedenti menziona, è necessario essere a conoscenza delle sequenze di lettura e di aggiornamento, qualcosa come incrementi (INT NUM) che probabilmente invocherà Geti () e SETI () - In questo caso potresti aggiungere un 'sincronizzatoIncrementi (int num) 'Metodo alla tua classe di esempio.Il bloccaggio viene quindi fatto ad un livello più alto, riducendo la necessità di blocchi di lettura e scrittura separati ed è oo amichevole come dati e comportamento stare insieme.Questa tecnica è ancora più utile se stai leggendo / aggiornando diversi campi contemporaneamente.

Anche se sei semplicemente, leggere / scrivere / aggiornare un campo alla volta, quindi le classi AtomicXX sono più appropriate

Non è necessario utilizzare il blocco su tipi primitivi, stringa (sono immutabili) e tipi di thread-svuoti (come collezioni dal pacchetto "simultaneo").

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