2009-10-19 4 views
1

Nous concevons actuellement une application serveur multithread. Pour optimiser les performances, nous avons décidé d'implémenter un ReadWriteLock, c'est-à-dire que plusieurs threads peuvent obtenir un verrou s'ils veulent uniquement lire mais qu'un seul thread peut contenir le verrou en écriture.Mauvaise équité avec un ReadWriteLock/SharedLock sous charge

Ce verrou est utilisé avec une liste et l'itération sur la liste est l'opération de "lecture".

Maintenant, ce changement de mutex simple a effectivement augmenté les performances mais seulement à un certain niveau de concurrence. S'il y a plus de threads, ceux qui attendent le verrou en écriture, meurent de faim car avant qu'un itérateur ne se déverrouille, un autre itérateur se verrouille souvent déjà.

Toute idée/approche par défaut pour fournir plus d'équité aux threads voulant changer la liste tout en obtenant de meilleures performances?

Répondre

1

La solution à cela est généralement MVCC si votre problème le permet. MVCC permettrait aux lecteurs de continuer à lire une ancienne version, tandis que l'auteur pourrait mettre à jour en créant une nouvelle version.

Le problème que vous décrivez d'avoir à attendre que tous les lecteurs se terminent avant que l'enregistreur puisse se verrouiller est commun. Si vous ne pouvez pas mettre à jour vos données, pensez à réduire la taille du verrou. Un exemple de ceci est le ConcurrentHashMap en Java. En interne, il crée par défaut 16 verrous, ce qui permet de verrouiller des parties de la carte sans verrouiller l'ensemble de l'objet. Une dernière idée consiste à essayer de supprimer ReadWriteLock tout à fait, et d'utiliser un algorithme sans verrou. Cela peut être le plus difficile, et peut réduire la concurrence multi-core.

+1

Salut, nous avons pensé à quelque chose comme MVCC mais je ne pouvais pas le nommer. Je vous remercie. La stratégie de la carte de hachage est plus facile si vous avez un espace de hachage, pas avec une liste ordonnée comme nous utilisons maintenant. Des algorithmes optimistes sans verrouillage sont une option, je suis d'accord, mais comme vous l'avez dit, nous voulions éviter la mise en œuvre difficile. – Tarnschaf

1

En lisant l'OP, j'ai l'impression qu'il n'y a pas de file d'attente pour les demandes de verrouillage en lecture et en écriture?

L'approche normale consiste à mettre en file d'attente les demandes de verrouillage et à les traiter dans l'ordre.

Alors, imaginez un verrou d'écriture est tenue et un tas de demandes de verrouillage (lecture et écriture) viennent dans

Vous aurez alors une file d'attente de demandes quelque chose comme ça.

RRRRRWRRRWRWRWWRRRRR

Vous pouvez accorder des requêtes de lecture jusqu'à la première écriture. Vous attendez la fin des lectures, puis laissez un écrivain. Quand il a fini, vous pouvez encore accorder des lectures jusqu'à l'écriture suivante. Quand une écriture se termine et que la prochaine demande est une écriture, vous pouvez bien sûr n'accorder qu'à cette seule écriture. Je dois dire que ce sont des choses fondamentales - j'ai appris cette deuxième année sur mon diplôme. Je suis préoccupé par le fait que vous avez implémenté votre solution actuelle comme vous l'avez fait. Vous devez lire un texte de base décent sur le verrouillage.

+0

Merci, nous utilisions en fait une file d'attente mais pas avec la logique supplémentaire que vous décrivez qui ne continue pas jusqu'à ce que l'écriture puisse commencer. J'ai également proposé une solution comme la vôtre mais nous sommes satisfaits de notre solution actuelle: chaque écriture est faite en quelque sorte comme un "backbuffer". Chaque lecture obtient la version "stable" des données. Dès qu'une écriture se termine, un (nouveau) lecteur obtient la nouvelle version. – Tarnschaf

+0

Pourquoi utilisiez-vous une file d'attente non-ordonnée?Si vous avez un seul verrou, comme un mutex, le système d'exploitation mettra automatiquement en attente toutes les demandes en attente. –