PDA

Visualizza la versione completa : [Win/Py 2.7] Aiuto threading


zacca94
30-05-2017, 23:26
# -*- 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:

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()

MItaly
01-06-2017, 07:24
Uhm perché a prova1 e prova2 dovrebbe importare qualcosa del lock, visto che lo acquisisce solo prova3?

zacca94
01-06-2017, 09:26
Senza che apro un nuovo post:

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?

Ipotizziamo :


# -*- 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 di tutto

MItaly
04-06-2017, 22:28
Onestamente non ho capito che cosa stai cercando di fare; stiamo parlando di lock e nel codice tiri in ballo code di eventi usate a caso? :confused: Spiega il caso d'uso (=il problema che stai cercando di risolvere) e cerchiamo di capire come si può affrontare.

zacca94
06-06-2017, 13:23
il primo problema l'ho risolto... il lock non serve per bloccare nulla... ma per dare una precenza ad una risorso condivisa nel momento in cui viene utilizzata da due thread differenti, no?

Ora il secondo esempio utilizza "male" la queue per dare delle bloccare/unbloccare... volevo sapere come potrei fare una cosa simile in maniera elegante e più intelligente (la mia è palese sia fatta male, persino da me che non conosco i thread)

MItaly
08-06-2017, 01:14
il primo problema l'ho risolto... il lock non serve per bloccare nulla... ma per dare una precenza ad una risorso condivisa nel momento in cui viene utilizzata da due thread differenti, no?
Un lock in genere serve per evitare che più thread accedano alla stessa risorsa in contemporanea, ovvero a garantire che certe operazioni siano atomiche. Se ho due thread che incrementano la stessa variabile contatore senza un lock, alla fine il conteggio sarà sbagliato, perché l'incremento di per sé non è atomico - è composto da lettura della variabile, incremento, scrittura della variabile, e se queste operazioni si mischiano tra un thread e l'altro i risultati saranno errati.
Per questo in una circostanza del genere si usa un lock, che tutti si impegnano ad acquisire prima di mettere mano ad una risorsa condivisa. Quando uno ha acquisito il lock ha la sicurezza di avere la risorsa tutta per sé, dato che se qualcun altro cerca di acquisire il lock a sua volta viene tenuto fermo fino a quando il primo thread non lo rilascia.


Ora il secondo esempio utilizza "male" la queue per dare delle bloccare/unbloccare... volevo sapere come potrei fare una cosa simile in maniera elegante e più intelligente (la mia è palese sia fatta male, persino da me che non conosco i thread)
Ribadisco che non riesco a capire nemmeno cosa vorresti ottenere in quel codice.

zacca94
08-06-2017, 09:19
mettere in wait/slobccare a prova didattica thread a mia scelta

MItaly
09-06-2017, 00:05
Metti un lock per ogni thread, acquisiscilo all'inizio del loop e liberalo alla fine; per bloccare un thread, acquisiscilo anche "da fuori". Ma di nuovo, un esempio del genere non serve a granché didatticamente, i lock e le altre primitive di sincronizzazione in genere non vengono usate così.

zacca94
09-06-2017, 12:06
Appunto...

Il mio esempio era tipo "ipotizziamo che ho un programma nel quale cè un pulsante [aggiorna database] e quando ci clicco devo stoppare il thread che estrae dati dal database".
Questo era un pratico esempio didattico di utilizzo..

Loading