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

    Conflitto tra 2 thread

    Ciao!
    Ho un codice per fare delle prove sul funzionamento dei thread in Java. Non sono molto esperto , ma i due thread, creati da due oggetti diversi, dovrebbero essere indipendenti e agire su variabili indipendenti.
    Dall'output del programma però non sembra che le cose vadano così, nonostante gli array hi[] separati (uno per ciascun oggetto) e i metodi dichiarati synchronized. A volte uno dei due array non viene inizializzato, a volte uno contiene soltanto una parte dei valori corretti. Perché succede questo? Come si può evitare?
    Grazie,

    Fabio





    codice:
    package pack1;
    
    public class Thread1Example {
    
    	public static void main(String[] args) {
    		
    		Writer w1 = new Writer("Thread1");
    		Writer w2 = new Writer("Thread2");
    		String[] arr =  new String[10];
    		w1.setString(arr);
    		w2.setString(arr);	
    		
    		w1.start();
    		w2.start();
    		
    		w1.printString();
    		w2.printString();
    	}
    
    }
    
    package pack1;
    
    public class Writer extends Thread {
    
    	  private volatile String[] hi = new String[10];
    	  private String name1;
    	  public Writer(String nam)
    	  {
    		  super(nam);
    		  this.name1 = nam;
    	  }
    	  public synchronized void printString()
    	  {
    		  int n=0;
    		  
    		  System.out.println("This array belongs to " + this.name1);
    		  
    		  for(n=0;n<10;n++)
    		  {
    			  System.out.println(hi[n]);
    		  }	  
    		  
    	  }
    	  public void setString(String[] hii)
    	  {
    		  hi=hii;
    	  }
    	  public void run()
    	  {
    
    		method1();		  
    	  }
    	  public synchronized void method1()
    	  {
    		  int n=0;
    		  for(n=0;n<10;n++)
    		  {
    			  if(name1.compareTo("Thread1")==0)
    			  {
    				  hi[n]="yes";
    				  try
    				  {
    		
    				  }
    			  		  catch(Exception except)
    			  		  {
    			  			  System.out.print(except);
    			  		  }
    			  }
    			  else
    			  {
    				  hi[n]="no";
    
    				  try
    				  {
    
    				  }
    			  		  catch(Exception except)
    			  		  {
    			  			  System.out.print(except);
    			  		  }
    			  }
    				  
    		  }
    	
    	}
    }

    L'output è (e cambia quasi ogni volta che si esegue il programma):

    codice:
    This array belongs to Thread1
    null
    null
    null
    null
    null
    null
    null
    null
    null
    no
    This array belongs to Thread2
    no
    no
    yes
    yes
    yes
    yes
    yes
    yes
    yes
    yes

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

    Re: Conflitto tra 2 thread

    Originariamente inviato da bubble8o8
    A volte uno dei due array non viene inizializzato, a volte uno contiene soltanto una parte dei valori corretti. Perché succede questo? Come si può evitare?

    codice:
    		Writer w1 = new Writer("Thread1");
    		Writer w2 = new Writer("Thread2");
    		String[] arr =  new String[10];
    		w1.setString(arr);
    		w2.setString(arr);	
    		
    		w1.start();
    		w2.start();
    		
    		w1.printString();
    		w2.printString();
    Non ho letto tutto il codice ma ho subito notato il pezzo che ho quotato.
    Devi tenere presente una cosa importante: start() fa solo passare il thread in stato "runnable" e ritorna praticamente immediatamente. Attenzione: non attende la fine del thread!!

    Quindi quando invochi quelle due printString i due thread potrebbero anche non essere nemmeno partiti o magari solo uno è appena partito.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    start() fa solo passare il thread in stato "runnable" e ritorna praticamente immediatamente. Attenzione: non attende la fine del thread!!

    Quindi quando invochi quelle due printString i due thread potrebbero anche non essere nemmeno partiti o magari solo uno è appena partito.
    Ok! Nella guida non c'era scritto esplicitamente. Ma come faccio a lanciare i due printString soltanto quando sono sicuro che tutti e due i thread hanno finito l'esecuzione? Esiste un flag o attributo dei due oggetti che posso verificare?

    Fabio

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da bubble8o8
    Ma come faccio a lanciare i due printString soltanto quando sono sicuro che tutti e due i thread hanno finito l'esecuzione?
    join() su un Thread.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    join() su un Thread.
    Ho modificato il main così:

    codice:
    		Writer w1 = new Writer("Thread1");
    		Writer w2 = new Writer("Thread2");
    		String[] arr =  new String[10];
    		w1.setString(arr);
    		w2.setString(arr);	
    		
    		w1.start();
    		
    		try{
    			w1.join();
    		}
    		catch(Exception ex){
    			System.out.println("Eccezione");
    		}
    		
    		w2.start();
    		
    		try{
    			w2.join();
    		}
    		catch(Exception ex){
    			System.out.println("Eccezione");
    		}
    				
    		w1.printString();
    		w2.printString();

    Ma l'output è:

    codice:
    Thread1
    Thread2
    This array belongs to Thread1
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    This array belongs to Thread2
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no

    Il primo array ovviamente dovrebbe essere fatto da tutti "yes" e il secondo da tutti "no".
    Se faccio eseguire prima w2 e dopo w1, tutte le voci sono "yes". Se non ti ho ancora annoiato, che cosa può essere?

    Fabio

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da bubble8o8
    codice:
    		w1.start();
    		
    		try{
    			w1.join();
    		}
    		catch(Exception ex){
    			System.out.println("Eccezione");
    		}
    		
    		w2.start();
    		
    		try{
    			w2.join();
    		}
    		catch(Exception ex){
    			System.out.println("Eccezione");
    		}
    				
    		w1.printString();
    		w2.printString();
    Con questa modifica c'è una sequenzialità ben precisa: Thread1 esegue e termina prima di Thread2.

    Originariamente inviato da bubble8o8
    Il primo array ovviamente dovrebbe essere fatto da tutti "yes" e il secondo da tutti "no".
    Se faccio eseguire prima w2 e dopo w1, tutte le voci sono "yes".
    Stai dimenticando una cosa: l'array è in "comune" tra i due thread:

    codice:
            String[] arr =  new String[10];
            w1.setString(arr);
            w2.setString(arr);
    Thread1 quindi setta 10 "yes" e Thread2 setta 10 "no". Tu invochi printString su ciascun Writer ma essendo lo stesso array, lo stampi 2 volte. E lo stato ovviamente è l'ultimo impostato: quindi tutti "no".


    P.S. Sinceramente non ho capito cosa stai tentando di provare o testare con questi 2 thread. Visto che, tra l'altro, con la tua ultima modifica dei join non c'è nemmeno "concorrenza" tra i due thread.


    Originariamente inviato da bubble8o8
    Se non ti ho ancora annoiato
    Nessun problema, figurati.
    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.