Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13

Discussione: [Java] Synchronized

  1. #1
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    378

    Synchronized

    ciao, sto facendo delle prove per gestire la sincronizzazione fra due o più threads.
    sto provando a lanciare due thread e fare in modo che il secondo non scriva nella lista finchè il primo non finisce...

    Codice PHP:
    public class Test {

        public static 
    void main(String[] argv){
            
    ThreadsSincronizzati threadSincronizzati = new ThreadsSincronizzati();
            }

        } 
    Codice PHP:
    import java.util.*;

    public class 
    ThreadsSincronizzati {

        public static 
    Lista miaLista;
        private 
    Thread01 thread01;
        private 
    Thread02 thread02;
        private 
    ThreadStampa threadStampa;
        
        public 
    ThreadsSincronizzati(){
            
    miaLista = new Lista();
            
    thread01 = new Thread01();
            
    thread02 = new Thread02();
            
    threadStampa = new ThreadStampa();
            
            
    thread01.start();
            
    thread02.start();
            
    threadStampa.start();
            }
        
        } 
    Codice PHP:
    import java.util.*;

    public class 
    Lista {
        
        private static 
    ArrayList lista;
        
        public 
    Lista(){
            
    lista = new ArrayList();
            }

        public 
    synchronized void aggiungi(String testo){
            
    lista.add(testo);
            }
        
        public 
    synchronized void stampa(){
            for(
    int i 0lista.size(); i++){
                
    System.out.println(lista.get(i));
                }
            }
        
        } 
    Codice PHP:
    public class Thread01 extends Thread {

        public 
    void run(){
            
    System.out.println("ESECUZIONE THREAD 01");
            for(
    int i 0100++){
                
    ThreadsSincronizzati.miaLista.aggiungi("THREAD01 " i);
                try{    
                    
    this.sleep(20);
                    }
                catch(
    Exception err){
                    
    System.out.println("ERRORE THREAD 01");
                    }
                }
            }

        } 
    Codice PHP:
    public class Thread02 extends Thread {

        public 
    void run(){
            
    System.out.println("ESECUZIONE THREAD 02");
            for(
    int i 0100++){
                
    ThreadsSincronizzati.miaLista.aggiungi("THREAD02 " i);
                try{    
                    
    this.sleep(20);
                    }
                catch(
    Exception err){
                    
    System.out.println("ERRORE THREAD 01");
                    }
                }
            }

        } 

    ho provato e riprovato ma i due threads continuano a scrivere nella lista in modo alternat...

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

    Re: Synchronized

    Originariamente inviato da bmw
    ciao, sto facendo delle prove per gestire la sincronizzazione fra due o più threads.
    sto provando a lanciare due thread e fare in modo che il secondo non scriva nella lista finchè il primo non finisce...

    ho provato e riprovato ma i due threads continuano a scrivere nella lista in modo alternat...
    Beh, certo. L'oggetto Lista è uno solo utilizzato da entrambi i thread e questo è ok (non è il massimo tenere il reference a Lista come campo statico, sarebbe stato più corretto passare ad entrambi i thread il reference. Ma sono questioni più di "design").

    Ma il fatto che hai messo synchronized sul metodo aggiungi() vuol solo dire che solamente 1 thread per volta può eseguire il metodo e quindi fare la lista.add(). Insomma, la "esclusività" è solo nella esecuzione del metodo. Se vuoi che un thread possa chiamare per 100 volte consecutive aggiungi() in modo "atomico" (ed è qui il nocciolo della questione), allora devi acquisire il lock per tutto il ciclo di inserimento!

    Visto che il lock è fatto sulla istanza dell'oggetto, allora è possibile fare il "client-side locking" e dovresti fare:

    codice:
            synchronized(ThreadsSincronizzati.miaLista) {
                for(int i = 0; i < 100; i ++){
                    ThreadsSincronizzati.miaLista.aggiungi("THREAD01 " + i);
                    try{    
                        this.sleep(20);
                        }
                    catch(Exception err){
                        System.out.println("ERRORE THREAD 01");
                        }
                    }
                }
            }
    (idem nell'altro thread) In tal caso tutto il ciclo di inserimento diventa "atomico". È anche chiaro, che visto cosa fa il thread, in particolare la sleep, il lock è mantenuto per molto molto tempo. Tu stai facendo un esempio "didattico", diciamo. Ma in casi reali, una cosa del genere sarebbe "troppo".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    378
    Ciao intanto ti irngrazio, sei davvero molto gentile! Si è una prova didattica per farmi un'idea di come funziona. L'idea era quella di provare a scrivere il modo esclusivo su di una risolrsa condivisa fra più threads. Effettivamente già il codice funzionava, ma mi ero fissato che dovesse scrivere prima un thread (eseguisse tutti il ciclo for), poi il secondo e così via. Invece era giusto come avevo fatto, l'importante era che in nessun caso due o più threads scrivessero contemporanemente sulla stessa risorsa.

    Beh, certo. L'oggetto Lista è uno solo utilizzato da entrambi i thread e questo è ok (non è il massimo tenere il reference a Lista come campo statico, sarebbe stato più corretto passare ad entrambi i thread il reference. Ma sono questioni più di "design").
    Ho risistemato il codice, così è migliore ??

    Codice PHP:
    public class Test {

        public static 
    void main(String[] argv){
            
    ThreadsSincronizzati threadSincronizzati = new ThreadsSincronizzati();
            }

        } 

    Codice PHP:
    import java.util.*;

    public class 
    ThreadsSincronizzati {

        private 
    Lista lista;
        private 
    Thread01 thread01;
        private 
    Thread02 thread02;
        private 
    ThreadStampa threadStampa;
        
        public 
    ThreadsSincronizzati(){
            
    lista = new Lista();
            
    thread01 = new Thread01(lista);
            
    thread02 = new Thread02(lista);
            
    threadStampa = new ThreadStampa(lista);
            
            
    thread01.start();
            
    thread02.start();
            
    threadStampa.start();
            }
        
        } 


    Codice PHP:
    import java.util.*;

    public class 
    Lista {
        
        private static 
    ArrayList lista;
        
        public 
    Lista(){
            
    lista = new ArrayList();
            }

        public 
    synchronized void aggiungi(String testo){
            
    lista.add(testo);
            }
        
        public 
    synchronized void stampa(){
            for(
    int i 0lista.size(); i++){
                
    System.out.println(lista.get(i));
                }
            }
        
        } 


    Codice PHP:
    public class Thread01 extends Thread {

        private 
    Lista lista;
        
        public 
    Thread01(Lista lista){
            
    this.lista lista;
            }
        
        public 
    void run(){
            
    System.out.println("ESECUZIONE THREAD 01");
            for(
    int i 0100++){
                
    lista.aggiungi("THREAD01 " i);
                try{    
                    
    this.sleep(20);
                    }
                catch(
    Exception err){
                    
    System.out.println("ERRORE THREAD 01");
                    }
                }
            }

        } 


    Codice PHP:
    public class Thread02 extends Thread {

        private 
    Lista lista;
        
        public 
    Thread02(Lista lista){
            
    this.lista lista;
            }
        
        public 
    void run(){
            
    System.out.println("ESECUZIONE THREAD 02");
            for(
    int i 0100++){
                
    lista.aggiungi("THREAD02 " i);
                try{    
                    
    this.sleep(20);
                    }
                catch(
    Exception err){
                    
    System.out.println("ERRORE THREAD 01");
                    }
                }
            }

        } 
    Ti ringrazio ancora e adesso provo a fa eseguire completamente un thread e poi passare l'esecuzione al successivo come mi hai mostrato nel codice che hai postato.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Non l'ho notato prima ma te lo segnalo adesso: nella classe Lista hai messo l'ArrayList come campo statico. Non va molto bene. Nel tuo caso è ok perché crei 1 solo Lista. Ma in generale non ha molto senso.
    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
    Registrato dal
    May 2006
    Messaggi
    378
    Dici che static non va bene perchè creo comunque un solo ArrayList e non ha senso che sia statico ??

    Forse ho capito male dove devo mettere synchronizated per fare in modo che tutto il ciclo for del primo thread venga eseguito e subito dopo venga eseguito tutto il ciclo for del secondo thread ??!?!

    Ho modificato così il run() del thread ma non cambia l'esecuzione...

    Codice PHP:
    public synchronized void run(){
            
    System.out.println("ESECUZIONE THREAD 01");
            for(
    int i 0100++){
                
    lista.aggiungi("THREAD01 " i);
                try{    
                    
    this.sleep(20);
                    }
                catch(
    Exception err){
                    
    System.out.println("ERRORE THREAD 01");
                    }
                }
            } 

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da bmw
    Dici che static non va bene perchè creo comunque un solo ArrayList e non ha senso che sia statico ??
    Se tieni quel campo static, va bene solo se crei 1 oggetto Lista. Se ne crei 2 o più ... quel campo static, essendo in comune, lo sovrascrivi!

    Originariamente inviato da bmw
    Ho modificato così il run() del thread ma non cambia l'esecuzione...
    Infatti non cambia. Perché mettendo il synchronized sul run(), si cerca di acquisire il lock sull'oggetto sui cui è invocato il run() ... che è il Thread01 o a seconda, Thread02.

    In sostanza il thread 1 cerca di acquisire il lock sulla istanza di Thread01 e il thread 2 cerca di acquisire il lock sulla istanza di Thread02. Sono due oggetti diversi, quindi non c'è contendimento tra i due thread!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    378
    Scusa ma allora non capisco il codice che mi hai postato ... quello dovrebbe riuscire a eseguire tutti il ciclo for del thread 1 prima di fa eseguire tutti il ciclo for del thread 2 ?

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da bmw
    Scusa ma allora non capisco il codice che mi hai postato ... quello dovrebbe riuscire a eseguire tutti il ciclo for del thread 1 prima di fa eseguire tutti il ciclo for del thread 2 ?
    Sì, perché ho usato il costrutto:

    synchronized (espressione) blocco

    a cui va specificato un reference dell'oggetto su cui acquisire il lock. E nell'esempio iniziale, l'oggetto comune era proprio la Lista referenziata da ThreadsSincronizzati.miaLista.

    Con le modifiche che hai fatto, ora dovresti fare il synchronized sul campo 'lista' che hai messo nei due thread. Se passi ad entrambi i thread lo stesso reference Lista, siamo nella stessa situazione di prima, cioè entrambi cercano di acquisire il lock sullo stesso oggetto.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    378
    ..niente non riesco a venirne fuori, contunua a eseguire alternativamente il thread 1 e il thread 2. Quando hai un attimo libero mi faresti un esempio di codice modificando l'esempio che ho postato per far eseguire prima tutti il thread 1 e poi tutto il thread 2 ??

    grazie ancora...

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da bmw
    Quando hai un attimo libero mi faresti un esempio di codice modificando l'esempio che ho postato per far eseguire prima tutti il thread 1 e poi tutto il thread 2 ??
    Facendo riferimento all'ultimo insieme di classi che hai postato, dovresti fare:

    codice:
        public void run() {
            synchronized (lista) {
                System.out.println("ESECUZIONE THREAD 01");
                for(int i = 0; i < 100; i ++) {
                    lista.aggiungi("THREAD01 " + i);
                    try {
                        this.sleep(20);
                    } catch(Exception err) {
                        System.out.println("ERRORE THREAD 01");
                    }
                }
            }
        }
    Idem (non ripeto per brevità) per Thread02.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

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.