[Win/Py 2.7] Aiuto threading

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 862
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

[Win/Py 2.7] Aiuto threading

Messaggio da TommyB1992 »

Codice: Seleziona tutto

# -*- coding: utf-8 -*-

class Boh(object):

    def __init__(self, **kwargs):
        self.__lock = Lock()

    def main(self):
        t1 = Thread(target=self.prova1)
        t2 = Thread(target=self.prova2)
        t3 = Thread(target=self.prova3)
        
        t1.start()
        t2.start()
        t3.start()
        
        """t1.join()
        t2.join()
        t3.join()"""
        
        while True:
            print 4
            sleep(1)


    def prova1(self):

        while True:
            print "1"
            sleep(1)
            
    def prova2(self):
        while True:
            print "2"
            sleep(1)
            
    def prova3(self):

        self.__lock.acquire()
        try:
            while True:
                print "3"
                sleep(10)
        finally:
            self.__lock.release()

if __name__ == "__main__":
    from time import sleep, time
    from threading import Thread, Lock

    Boh().main()
Sto studiando il multi-threading perciò siate pazienti per favore: perchè il "prova3()" non acquista il lock e non aspetta 10 secondi prima di procedere ad eseguire prova2() e prova1() ?

// Edit

Ho anche modificato con:

Codice: Seleziona tutto

    def prova3(self):

            while True:
                self.__lock.acquire()
                print "3"
                
                sleep(5)
                self.__lock.release()
Per acquisire il lock ogni start ciclo e rilasciarlo 5 secondi dopo la fine ma continuano ad eseguirsi quelli di prova2/1()
Avatar utente
Claudio_F
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1463
Iscrizione: lunedì 28 maggio 2012, 18:49
Desktop: Mate/Gnome
Distribuzione: Ubu22.04

Re: [Win/Py 2.7] Aiuto threading

Messaggio da Claudio_F »

Il lock viene acquisito regolarmente. Ma gli altri thread non provano anche loro ad acquisirlo per cui procedono indisturbati.

Per usare un lock, cioè un cartellino libero/occupato per accedere a una risorsa condivisa, tutti i thread che vogliono usare quella risorsa devono provare ad acquisire il lock, allora si il primo che lo acchiappa blocca gli altri finché non lo rilascia.
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 862
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [Win/Py 2.7] Aiuto threading

Messaggio da TommyB1992 »

Non mi è mica così chiaro...
Mi stai dicendo che dovrei dare il lock a tutti i thread per poter dare "una priorità"?
Quindi con il lock non posso dare la precedenza ad 1 solo thread?
Se io volessi fare quella cosa come nell'esempio come dovrei fare?

Codice: Seleziona tutto

        def prova3(self):

                while True:
                    self.__lock.acquire()
                    print "3"
                    self.__lock.release()                   
                    sleep(5)

ipotizziamo che voglio eseguire questo codice 1a volta ogni 10 secondi, e quando ci entra voglio mettere in pausa prova1, come posso fare?

p.s. so che teoricamente grazie alla condivisione di stato posso creare una variabile e fare così:

Codice: Seleziona tutto

   myLock = False

    def prova1(self):

        while True:
            if not self.myLock:
                print "1"
            sleep(1)
           
    def prova3(self):

            while True:
                self.myLock = True
                print "3"
                self.myLock = False
                sleep(10)

Però... ipotizzando di utilizzare "bene" i thread come dovrei fare?
Avatar utente
Claudio_F
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1463
Iscrizione: lunedì 28 maggio 2012, 18:49
Desktop: Mate/Gnome
Distribuzione: Ubu22.04

Re: [Win/Py 2.7] Aiuto threading

Messaggio da Claudio_F »

TommyB1992 ha scritto:Quindi con il lock non posso dare la precedenza ad 1 solo thread?
No, il lock non serve a bloccare un altro thread specifico, ma ad arbitrare l'accesso ad una risorsa condivisa. Il primo che arriva blocca gli altri che vogliono usare quella risorsa (cioè quelli che provano a fare una acquire su quello stesso lock in quello stesso momento), quando rilascia il lock uno degli altri in attesa lo acquisisce e si sblocca, e così via. Si possono creare molti lock da usare ciascuno per accedere ad una diversa risorsa condivisa (ed è facilissimo bloccarsi in deadlock).
voglio mettere in pausa prova1, come posso fare?
Non ho mai provato, ma forse un oggetto threading.Event potrebbe svolgere la funzione richiesta.
Però... ipotizzando di utilizzare "bene" i thread come dovrei fare?
Idealmente i thread (o i processi se si usa multiprocessing) dovrebbero comunicare tramite queue (certo che in un esempio ristretto come quello postato è più il codice necessario a scrivere/leggere le queue che il resto).
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 862
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [Win/Py 2.7] Aiuto threading

Messaggio da TommyB1992 »

Ok mi hai tolto molti dubbi e te ne sono grato.
Vediamo se ho capito, per esempio se ho una funzione che fa il read di un file acceduta da più thread ha senso lockare giusto?

anche se ora ne ho altri:
- Come faccio a mettere in wait thread da altri thread?
- Le queue sono molto scomode per comunicare!

Tecnicamente dovrei scrivere una classe faccia da "handler"...

Ipotizziamo :

Codice: Seleziona tutto

# -*- coding: utf-8 -*-

class Example(object):
    def __init__(self, e, q):
        self.e = e
        self.q = q
    
    def main(self):
        Thread(target=self.thread1, args=(self.e, self.q)).start()
        Thread(target=self.thread2, args=(self.e, self.q)).start()
        Thread(target=self.thread3, args=(self.e, self.q)).start()
        
    def thread1(self, e, q):
        while True:
            if q.empty():
                print "Thread 1"
            else:
                try:
                    print q.get()
                    print "Size:", q.qsize()
                except:
                    print "Size:", q.qsize()
                e.clear() # For security reason
                e.set()
                e.wait()

            sleep(1)

    def thread2(self, e, q):
        c = 0
        while True:
            print "Thread 2"
            if c > 5: # and e.isSet():
                try:
                    print "Clear"
                    e.clear()
                except:
                    print "Err clear"
            
            c += 1
            sleep(5)

    def thread3(self, e, q):
        c = 0
        while True:
            print "Thread 3"
            if c == 1:
                q.put("Block")
            
            
            c += 1
            sleep(10)

if __name__ == "__main__":
    from time import sleep, time
    from threading import Thread, Event
    from Queue import Queue

    Example(q = Queue(1), e = Event()).main()
Queste righe di codice che ho scritto funzionano per "bloccare" e "sbloccare" il thread1().

Ma se volessi in qualche modo sbloccare solo 1 thread? e.clear() da come ho capito li sblocca tutti no? L'unica soluzione che mi viene in mente e sbloccarli tutti con e.clear() e poi bloccare subito quelli di cui non sono più interessato.

Grazie ancora di tutto
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 2 ospiti