2 votes

Lâcher temporairement un verrou s'il est maintenu, en python

J'ai plusieurs méthodes différentes qui ne sont pas censées s'exécuter simultanément, donc j'utilise un verrou unique pour les synchroniser. Cela ressemble à ceci :

selected_method = choose_method()
with lock:
    selected_method()

Dans certaines de ces méthodes, il m'arrive parfois d'appeler une fonction d'aide qui effectue des entrées-sorties réseau lentes. (Appelons-la network_method()). Je voudrais libérer le verrou pendant que cette fonction s'exécute, pour permettre aux autres threads de continuer leur traitement.

Une façon d'y parvenir serait d'appeler lock.release() et lock.acquire() avant et après l'appel de la méthode réseau. Cependant, je préférerais que les méthodes ne soient pas conscientes du verrou, car il y en a beaucoup et elles changent tout le temps.

Je préférerais beaucoup réécrire network_method() pour qu'elle vérifie si le verrou est détenu, et si c'est le cas, le libérer avant de commencer et le reprendre à la fin.

Remarquez que network_method() est parfois appelée depuis d'autres endroits, donc elle ne devrait pas libérer le verrou si ce n'est pas sur le thread qui le détient.

J'ai essayé d'utiliser la méthode locked() sur l'objet Lock, mais cette méthode ne me dit que si le verrou est détenu, pas s'il est détenu par le thread actuel.

Par ailleurs, le verrou est un objet global et cela me convient.

3voto

Kylotan Points 14114

Je préférerais beaucoup réécrire network_method() pour qu'il vérifie si le verrou est détenu, et s'il l'est, le libère avant de commencer et le réacquiert à la fin.

Notez que network_method() est parfois appelé depuis d'autres endroits, donc il ne devrait pas libérer le verrou s'il n'est pas sur le fil qui le détient.

Cela semble tout simplement être la mauvaise chose à faire :(

Tout d'abord, il est mauvais d'avoir une fonction qui a parfois un autre effet secondaire magique en fonction de l'endroit où vous l'appelez. C'est le genre de chose qui est un cauchemar à déboguer.

Deuxièmement, un verrou devrait avoir des sémantiques claires d'acquisition et de libération. Si je regarde du code qui dit "verrouiller(); faire_quelque_chose(); déverrouiller();" alors je m'attends à ce qu'il soit verrouillé pendant la durée de faire_quelque_chose(). En fait, cela me dit également que faire_quelque_chose() nécessite un verrou. Si je découvre que quelqu'un a écrit un faire_quelque_chose() particulier qui déverrouille en fait le verrou que je viens de voir verrouillé, je vais soit (a) les licencier, soit (b) les poursuivre avec des armes, selon que je suis en position de supériorité par rapport à eux ou non.

En passant, le verrou est un objet global et cela me convient.

D'ailleurs, c'est aussi pourquoi les variables globales sont mauvaises. Si je modifie une valeur, appelle une fonction, puis modifie à nouveau une valeur, je ne veux pas que cette fonction au milieu puisse revenir en arrière et modifier cette valeur de manière imprévisible.

Ma suggestion pour vous est la suivante : votre verrou est au mauvais endroit, ou fait la mauvaise chose, ou les deux. Vous dites que ces méthodes ne sont pas censées s'exécuter simultanément, mais vous voulez en fait que certaines d'entre elles le soient. Le fait que l'une d'entre elles soit "lente" ne peut en aucun cas rendre acceptable le retrait du verrou - soit vous avez besoin de l'exclusion mutuelle pendant ce type d'opération pour que ce soit correct, soit vous ne l'avez pas. Si l'opération plus lente est en effet intrinsèquement sûre alors que les autres ne le sont pas, alors peut-être qu'elle n'a pas besoin du verrou - mais cela implique que le verrou devrait être placé à l'intérieur de chacune des opérations plus rapides, pas à l'extérieur. Mais tout cela dépend de ce pour quoi le verrou est exactement.

0voto

FogleBird Points 23405

Pourquoi ne pas simplement faire cela?

with lock:
    before_network()
faire_des_trucs_de_réseau()
with lock:
    after_network()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X