In primo luogo, i blocchi sono progettati per proteggere le risorse; i thread non sono "bloccati" o "sbloccati"/acquisiscono/un blocco (su una risorsa) e/rilascia/un blocco (su una risorsa).
Lei ha ragione che si desidera thread per eseguire contemporaneamente il più possibile, ma diamo uno sguardo a questo:
y=10
def doStuff(x):
global y
a = 2 * y
b = y/5
y = a + b + x
print y
t1 = threading.Thread(target=doStuff, args=(8,))
t2 = threading.Thread(target=doStuff, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
Ora, si potrebbe sapere che uno di questi fili potrebbero completare e stampare prima . Ci si aspetterebbe di vedere entrambe le uscite 30.
Ma potrebbero non farlo.
y è una risorsa condivisa e, in questo caso, i bit che leggono e scrivono su y fanno parte di quella che viene definita una "sezione critica" e dovrebbero essere protetti da un blocco. La ragione è che non si ottengono unità di lavoro: o thread può ottenere la CPU in qualsiasi momento.
Pensateci in questo modo:
T1 è felicemente l'esecuzione di codice e colpisce
a = 2 * y
Ora T1 ha a = 20 e si ferma l'esecuzione per un po '. t2 diventa attivo mentre t1 attende più tempo della CPU. t2 esegue:
a = 2 * y
b = y/5
y = a + b + x
a questo punto la variabile y globale = 30
t2 ferma ferma per un po 'e t1 riprende. esegue:
b = y/5
y = a + b + x
Dal y era il 30 quando b è stato impostato, b = 6 e y è ora impostato su 34.
l'ordine delle stampe non è deterministico come bene e si potrebbe ottenere la 30 prima o prima 34.
mezzo di una serratura si avrebbe:
global l
l = threading.Lock()
def doStuff(x):
global y
global l
l.acquire()
a = 2 * y
b = y/5
y = a + b + x
print y
l.release()
Questo rende necessariamente questa sezione di codice lineare - solo thread alla volta. Ma se l'intero programma è sequenziale, non dovresti comunque usare i thread. L'idea è di aumentare la velocità in base alla percentuale di codice che è possibile eseguire al di fuori dei blocchi e correre in parallelo. Questo è (uno dei motivi) il motivo per cui l'utilizzo di thread su un sistema a 2 core non raddoppia le prestazioni per tutto.
il blocco stesso è anche una risorsa condivisa, ma deve essere: una volta che un thread acquisisce il blocco, tutti gli altri thread che tentano di acquisire lo/same/lock verranno bloccati finché non viene rilasciato. Una volta rilasciato, il primo thread per spostarsi in avanti e acquisire il blocco bloccherà tutti gli altri thread in attesa.
Speriamo che sia abbastanza per andare avanti!
No, non sto chiedendo del GIL, conosco i limiti di esso in Python e sono felice con esso, la domanda riguarda il locking dei thread con acquire() e release() non relativi al GIL (diverso da esso ha bloccato il nome) – MistahX
È stato ricodificato, in quanto non esclusivo per 'python'. –
retagurato come python, mi riferisco ai metodi di blocco nel modulo di threading, ho dimenticato di aggiungere che in – MistahX