Le concept de verrous lecture-écriture est simple, permettant à plusieurs threads d’acquérir des verrous de lecture simultanément, mais un seul thread est autorisé à obtenir des verrous d’écriture simultanément, ce qui l’appelle aussi verrous exclusifs partagés. En C#, il est recommandé d’utiliser la classe ReaderWriterLockSlim pour compléter la fonction de verrouillage lecture/écriture. Dans certains cas, le nombre de lectures d’un objet est bien supérieur au nombre de modifications, et s’il est simplement verrouillé par verrouillage, cela affectera l’efficacité de la lecture. Si un verrou lecture-écriture est utilisé, plusieurs threads peuvent lire l’objet simultanément, et il ne sera bloqué que lorsque l’objet est occupé par le verrou d’écriture. En termes simples, lorsqu’un thread entre en mode lecture, les autres threads peuvent toujours entrer en mode lecture, en supposant qu’un thread souhaite entrer en mode écriture à ce moment-là, il doit alors être bloqué. jusqu’à ce que le mode lecture se termine. De même, si un thread passe en mode écriture, les autres threads seront bloqués qu’ils veuillent écrire ou lire. Il existe deux façons d’entrer en mode écriture/lecture : EnterReadLock tente d’entrer dans l’état de verrouillage en mode écriture. TryEnterReadLock(Int32) tente d’entrer dans l’état de verrouillage en mode lecture, avec la possibilité de sélectionner un délai d’attente entier. EnterWriteLock tente d’entrer dans l’état de verrouillage en mode écriture. TryEnterWriteLock(Int32) tente d’entrer dans l’état de verrouillage en mode écriture, et le temps d’expiration peut être sélectionné. Il y a deux façons de sortir du mode écriture/lecture : ExitReadLock réduit le nombre récursif du mode lecture et sort du mode lecture lorsque le nombre résultant est 0 (zéro). ExitWriteLock réduit le nombre récursif du motif d’écriture et sort du mode écriture lorsque le nombre obtenu est 0 (zéro). Voici comment l’utiliser :
Vous pouvez voir que le thread 3 et le thread 4 peuvent entrer en mode lecture en même temps, tandis que le thread 5 peut entrer en mode écriture après 5 secondes (c’est-à-dire après que les threads 3 et 4 soient sortis du verrouillage de lecture). Modifiez le code ci-dessus, ouvrez d’abord 2 threads en mode écriture, puis ouvrez les threads en mode lecture, le code est le suivant :
Les résultats sont les suivants :
Comme vous pouvez le voir, le thread 3 et le thread 4 entrent tous deux en mode écriture, mais le thread 3 occupe d’abord le verrouillage d’écriture, donc le thread 4 doit attendre 10 secondes avant d’entrer. Les threads 5 et 6 doivent occuper le verrou de lecture, donc attendez que le thread 4 quitte le verrouillage d’écriture avant de continuer. TryEnterReadLock et TryEnterWriteLock peuvent définir un délai d’attente ; lors de l’exécution de cette phrase, le thread bloquera ici, si le verrou peut être occupé à ce moment-là, alors retourne true, si le temps d’attente n’a pas encore occupé le verrou, retourne false, abandonne l’occupation du verrou, et continue à exécuter directement le code suivant. EnterUpgradeableReadLock La classe ReaderWriterLockSlim propose un mode de lecture évolutif, qui diffère du mode lecture en ce qu’il peut également être mis à niveau en mode écriture en appelant les méthodes EnterWriteLock ou TryEnterWriteLock. Parce qu’un seul fil peut être en mode améliorable à la fois. Un thread qui entre en mode évolutif n’affectera pas le thread en mode lecture, c’est-à-dire que lorsqu’un thread entre en mode améliorable, un nombre quelconque de threads peut entrer en mode lecture simultanément sans bloquer. Si plusieurs threads attendent déjà d’acquérir un verrou d’écriture, exécuter EnterUpgradeableReadLock bloquera jusqu’à ce que ces threads expirent ou quittent le verrou d’écriture. Le code suivant montre comment passer à un verrouillage d’écriture en mode lecture évolutive.
L’impact des verrous de lecture/écriture sur les performances est évident. Le code de test suivant :
Le code ci-dessus simule le fonctionnement de 500 tâches, chacune occupant un fil de pool de threads, dont 20 sont des threads d’écriture et 480 threads de lecture sont simulés. Il faut 10 ms pour lire les données et 100 ms pour écrire afin de tester respectivement la méthode de verrouillage et la méthode ReaderWriterLockSlim. Une estimation peut être faite, pour ReaderWriterLockSlim, en supposant que 480 threads lisent simultanément, alors cela consomme 10 ms, 20 opérations d’écriture occupent 2000 ms, donc le temps consommé est de 2010 ms, et pour la méthode de verrouillage ordinaire, puisqu’elles sont toutes exclusives, 480 opérations de lecture occupent 4800ms + 20 opérations d’écriture 2000ms = 6800ms. Les résultats ont montré une amélioration notable des performances.
|