Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    60

    domanda su notify e wait

    La notify e notifyAll per risvegliare un thread funziona solo in un metodo synchronized?? non si può adottare in un metodo che non lo è? grazie

  2. #2
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    confondi i concetti: synchronized ti protegge da eventuali accessi contemporanei da parte di due thread differenti.

    notify viene utilizzato per indicare ad un thread in attesa di un evento che deve risvegliarsi, ma non è detto che il thread che è in attesa si trovi in un blocco sync!!
    RTFM Read That F*** Manual!!!

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Si può adottare, nel senso che nessuno ti vieta di farlo, ma che senso avrebbe? Se un metodo (o porzione di codice) non è sincronizzato, nessun thread si bloccherà nell'eseguirlo contemporaneamente ad un altro... quindi a che serve notificare un "risveglio" quando (potenzialmente) nessun thread è bloccato?

    A meno che tu non voglia risvegliare qualcun altro, bloccato da qualche altra parte...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    60
    Ma potete spiegarmi perchè poi non si risvegliano con la notifyAll.

    Io avvio i client (il primo è giocatore BIANCO e fa il wait, poi il GIALLO e fa wait() e infine il NERO che dovrebbe riavegliarli ma non lo fa).
    Cosa sbaglio??

    Questo è il codice del ServerThread:
    codice:
    public synchronized void controlloInizio() throws InterruptedException, IOException{
    		if(giocatore.equals(Giocatore.NERO)){
    			partitaIniziata();
    			notifyAll();
    			out.println("sveglio tutti  ");
    			out.flush();
    		}
    		else{		
    		wait();
    		out.println("sveglio  ");
    		out.flush();
    		}
    	}
    
    public synchronized void run() {
    		
    		in = new Scanner(socket.getInputStream());
    		out = new PrintWriter(socket.getOutputStream());
    		out.println("Giocatore " + giocatore + " connesso  ");
    		out.flush();
    		controlloInizio();
    }

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Non stai usando nel modo corretto la sincronizzazione.

    Per prima cosa i thread dovrebbero sincronizzarsi su un oggetto in comune a tutti. Quindi, NON su essi stessi e, di conseguenza, non ha alcun senso rendere sincronizzati il run() e, generalmente, i metodi dei thread. Ciò che dovrebbe essere sincronizzato è l'accesso alla risorsa condivisa.

    In secondo luogo, il wait() dovrebbe essere posto sotto condizione e all'interno di un ciclo, in modo che se più thread vengono risvegliati, solo uno acquisisca il lock necessario e gli altri tornino in wait.

    L'argomento "sincronizzazione" dei thread non è così semplice. Va studiato bene e capito esattamnte il meccanismo.

    In linea di principio, la situazione può essere descritta in questo modo:

    codice:
    class MioThread extends Thread {
       ...
       @Override
       public void run() {
          ...
          mioOggettoCondiviso.accedoAllaRisorsaCondivisa();
          ...
       }
    }
    
    class MioOggettoCondiviso ... {
       ...
       public synchronized void accedoAllaRisorsaCondivisa() {
          while ( condizionePerBloccareIlThread ) {
             try { wait(); } catch (InterruptedException ie) { ie.printStackTrace(); }
          }
    
          ...   // Parte di codice sottoposta a sincronizzazione
    
          notifyAll();   // Qui sblocco tutti... il primo che si sveglia vince
       }
    }
    I metodi sincronizzati non sono quelli del thread. Il thread deve solo svolgere una funzione... a lui non interessa che qualcuno lo possa fermare e mettere in attesa.

    La wait() è all'interno di un ciclo condizionato. In questo modo, apena due o più thread si risvegliano, controllano tutti la condizione, ma solo il primo che acquisisce il nuovo lock proseguirà... gli altri torneranno in wait. Chiaramente la condizione deve essere semanticamente corretta con la logica del programma.

    La notifyAll() la faccio, subito prima di lasciare la regione critica.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    60
    Ma perchè in questo codice preso dal libro si effettua la wait direttamente sul run() qual'è la differenza? grazie

    codice:
    class MioThread extends Thread
    {	private int num;
    	private int succ;
    	private MioThread[] ref;
    	private boolean stato;	//true: attivo	false: disattivo
    	public MioThread(int num, int succ)
    	{
    		this.num = num;
    		this.succ = succ;
    		this.stato = (num == 0);
    	}
    		
    	public void setArray(MioThread[] ar)
    	{
    		ref = ar;
    	}
    	
    	public synchronized void attiva()
    	{
    		stato = true;
    		notify();	// CON QUESTO FUNZIONA
    	}
    	
    	public synchronized void run()
    	{
    		try{	
    			while(!stato)
    				 wait();
    
    		Console.scriviStringa("MioThread "+num);		
    		}catch(InterruptedException e){	}
    		
    		if(succ!=-1)
    		{	ref[succ].attiva();
    		}
    	}
    }

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Quel codice è leggermente "più contorto".
    La sincronizzazione viene fatta su un array di oggetti Thread condiviso e contenente i riferimenti di ciascun thread... cerca di partire con qualcosa di più semplice...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

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.