Durante lo sviluppo della mia libreria di registrazione, ho studiato il codice sorgente del modulo standard logging
di CPython.
Una delle sue caratteristiche è che i gestori sono thread-safe . Si possono scrivere registri su un file da più thread senza il rischio che le linee siano danneggiate.
Ho analizzato le fonti del modulo logging
e ho capito che per garantire la sicurezza dei thread, ogni gestore utilizza il proprio Lock
che acquisisce e rilascia a ogni chiamata di registrazione. Puoi vedere questo qui .
Che senso ha fare questo anziché utilizzare un unico blocco che circonda il numero di chiamanti in tutto il mondo? Ad esempio, perché non acquisire il blocco in callHandlers()
funzione?
Vedo due vantaggi principali:
- Migliori prestazioni in quanto vi è un solo blocco acquisito e rilasciato
- Assicurarsi che i messaggi registrati siano visualizzati nello stesso ordine in tutti i gestori (si pensi ad esempio ai due gestori H1 e H2 e due thread che registrano rispettivamente M1 e M2, questo evita la possibilità che la sequenza
H1.handle(M1) -> H1.handle(M2) -> H2.handle(M2) -> H2.handle(M1)
accada)
Nella mia libreria di logging personale, posso tranquillamente fare qualcosa di simile per logger:
with self.lock:
for handler in self.handlers:
handler.handle(message) # No lock used in "handle()"
O sto trascurando qualcos'altro?