Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [JAVA] ReentrantReadWriteLock()

    In che casi è preferibile utilizzare ReentrantReadWriteLock piuttosto che un semplice ReentrantLock?

    E quali sono le differenze tra i due Lock?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [JAVA] ReentrantReadWriteLock()

    Originariamente inviato da ragnonerodocet
    In che casi è preferibile utilizzare ReentrantReadWriteLock piuttosto che un semplice ReentrantLock?

    E quali sono le differenze tra i due Lock?
    ReentrantReadWriteLock è una implementazione di ReadWriteLock, la cui documentazione inizia con:

    A ReadWriteLock maintains a pair of associated locks, one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

    Quindi un ReadWriteLock ha una coppia di lock, uno per operazioni di sola lettura (che può essere tenuto da più thread simultaneamente) e uno per operazioni di scrittura (usato in modo esclusivo).

    Immagina una collezione che sia in grado di sfruttare un ReadWriteLock: se un thread invoca un metodo della collezione che modifica la struttura, allora è una "scrittura", quindi deve acquisire il write-lock che è esclusivo. È logico ... solo 1 thread per volta deve poter modificare la collezione.
    Ma se più thread volessero semplicemente leggere dalla collezione, quindi senza modificarla? Se si usasse solamente un intrinsic lock o un ReentrantLock, sarebbe tutto una mutua esclusione, tra più thread di lettura e pure tra letture/scritture. Sarebbe troppo "serializzante" in pratica e quindi poco performante.

    Invece con un ReadWriteLock, più thread possono leggere dalla collezione, fintanto che il write-lock non è acquisito.
    E cosa dovrebbe succedere se dei thread cercano di acquisire il read-lock mentre il write-lock è acquisito? O se si cerca di acquisire un write-lock mentre ci sono dei thread che tengono il read-lock? Beh, qui c'è da leggere la documentazione .... (non mi ricordo di preciso nemmeno io ) perché ci sono diverse "policy" che riguardano il modo in cui si deve comportare nei vari casi di contendimento.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Praticamente questo implica che, ottenendo il readLock, più Thread che accedono in lettura ad una variabile possono mantenere quel lock senza problemi.
    Al contrario, un Thread che ottiene il writeLock per scrivere su una variabile lo ottiene in modo esclusivo, dunque altri thread che nel frattempo crecano di ottenerlo non lo ottengono.

    Ma allora, più "semplicemente", non si potrebbe dichiarare quella variabile come volatile, atomicizzando(o atomizzando?) gli accessi in lettura/scrittura?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da ragnonerodocet
    Praticamente questo implica che, ottenendo il readLock, più Thread che accedono in lettura ad una variabile possono mantenere quel lock senza problemi.
    Al contrario, un Thread che ottiene il writeLock per scrivere su una variabile lo ottiene in modo esclusivo, dunque altri thread che nel frattempo crecano di ottenerlo non lo ottengono.
    Comunque non devi pensare solo all'accesso di 1 variabile ... io ho fatto l'esempio di una collezione che è un caso tipico possibile. Ma potrebbe certamente anche essere un oggetto mutabile che ha 1 solo dato.

    Originariamente inviato da ragnonerodocet
    Ma allora, più "semplicemente", non si potrebbe dichiarare quella variabile come volatile, atomicizzando(o atomizzando?) gli accessi in lettura/scrittura?
    La semantica di volatile è tale da garantire solo la "visibilità", non la "atomicità".

    volatile va bene nel caso in cui c'è 1 solo thread che scrive sulla variabile e N thread che leggono. Se più thread devono poter scrivere contemporaneamente, allora volatile non va bene e l'accesso deve essere sincronizzato opportunamente.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da andbin
    volatile va bene nel caso in cui c'è 1 solo thread che scrive sulla variabile e N thread che leggono. Se più thread devono poter scrivere contemporaneamente, allora volatile non va bene e l'accesso deve essere sincronizzato opportunamente.
    Quest'ultima parte l'ho scritta in modo non proprio preciso ... (ero stanco e .. di fretta).

    Riguardo a 'volatile', il libro "Java Concurrency in Practice" spiega la questione molto bene e la riporto adesso, ovviamente con mie parole.

    L'uso di 'volatile' va bene solo quando tutte le seguenti condizioni sono presenti:

    a) Quando il nuovo valore della variabile non dipende dal suo valore attuale. Come ho detto prima, volatile garantisce la "visibilità" ma non la "atomicità". Quindi anche se una variabile 'pippo' è volatile, fare pippo++ non è affatto "atomico". La semantica di volatile non è così "forte" da garantire questo. In effetti pippo++ è una operazione composta da 3 operazioni separate: lettura+incremento+scrittura.
    Se il nuovo valore dipende dal valore attuale (come appunto un post-incremento), si può usare volatile ma solo a condizione che ci sia solamente 1 thread che scrive sulla variabile.

    b) Quando la variabile non viene usata in un "invariant" che coinvolge altre variabili di stato. Immaginiamo una classe Range che contiene 2 variabili di stato 'from' e 'to'. Possiamo stabilire che un "invariant" è il seguente: "il valore di 'from' deve sempre essere minore di 'to'". Quando si imposta il valore di una delle due variabili, bisogna chiaramente controllare l'altra, altrimenti l'invariant non reggerebbe.
    Si ha sicuramente una operazione composta del tipo check-then-act e quindi una semplice variabile volatile non va bene, bisogna usare una apposita sincronizzazione.

    c) Quando il locking non è richiesto per qualunque altro motivo.

    Se almeno una di queste condizioni non è presente, è necessario ricorrere alla sincronizzazione, come minimo con un intrinsic lock.

    Spero di aver chiarito.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Allora scusate ancora il disturbo, ma in molte definizioni della keyword volatile trovo definizioni simili a questa:

    The load, store, read, and write actions on volatile variables are atomic, even if the type of the variable is double or long.

    Dunque se ho 2 o più thread che cercano di accedere ad una variabile volatile in questo modo
    Class ThreadMio extends Thread {


    public ThreadMio (int o) {
    this.numeroACaso = o;
    }
    private int numeroACaso;
    private Numero c;
    public void run () {

    this.c.modifica(numeroACaso);


    }
    }

    Class Numero {

    private volatile int campoVolatile;

    public void modifica (int n){
    this.campoVolatile = n;
    }

    }
    non rendo atomica tale azione dichiarando volatile campoVolatile?

    Dunque non dovrei preoccuparmi se n Thread accedessero a tale variabile... non potrei avere problemi di "accavallamento" di operazioni di write...

    O non è affatto così?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.