J'ai une classe (exemple simplifié) comme:verrouillage sur plusieurs méthodes que si un fil est dans une certaine méthode
public class SomeCollection : ICloneable
{
public void Add(Item item) { /* ... */ }
public void Remove(Item item) { /* ... */ }
public Item Get(Key key) { /* ... */ }
/*
...
*/
public object Clone() { /* ... */ }
}
J'ai besoin que lorsqu'un fil entre clone() aucun autre thread ne peut entrer dans Ajouter ou Supprimer mais peut entrer dans Get. Au début, je pensais:
public void Add(Item item) { lock(addLock) { /* ... */ } }
public void Remove(Item item) { lock(removeLock) { /* ... */ } }
public object Clone(Item item)
{
lock(addLock)
{
lock(removeLock)
{
/* ... */
}
}
}
Cela fonctionne (je pense), mais présente certains inconvénients: * Je ne veux pas entrer dans deux fils Ajouter à bloquer une autre - je traite que plus profondément dans le code * Je vais devoir supporter les frais généraux de verrouillage pour chaque appel à Ajouter ou supprimer
Alors je pensais de cette
private volatile bool cloning = false; // notice the volatile keyword
public void Add(Item item)
{
int i = 0;
while(cloning)
{
if (i++ > 20)
throw new TimeoutException();
Thread.Sleep(50); // waits 50 milliseconds
}
/* ... */
} // and the same for Remove
public object Clone()
{
cloning = true;
try
{
/* do the cloning */
} finally { cloning = false; }
}
Cependant cette approche:
- est plus complexe
- Clone peut entrer alors qu'un fil n'a pas fini d'exécuter Ajouter ou supprimer
- ne paraît pas naturel
J'ai donné ReadWriterLockSlim un bref regard, mais ne semble pas cadrer mon scénario. J'ai besoin de cela parce que la méthode Clone prend du temps (peut prendre plus d'une seconde - la collection est ÉNORME) et une altération dans ce temps va faire exploser l'énumérateur (utilisé dans une boucle foreach). Oui, je dois utiliser foreach puisque la collection de clés sous-jacente n'expose pas autre chose qu'un IEnumerable.
Quoi de neuf recommandez-vous?
Oui, j'ai considéré la même chose: Clone - l'écrivain, Ajouter et supprimer en tant que lecteurs. Un, les noms d'opération sont inversés je veux dire Ajouter et supprimer sont vraiment faire des écrits et Clone fait une lecture. Mais cela ressemble plus à un non-problème. Deuxièmement, je ne comprends pas vraiment si elle va bloquer une opération de lecture pendant une écriture et bloquer une opération d'écriture pendant une lecture. Mais encore une fois, je devrais relire la documentation. J'espère que vous avez raison à ce sujet. Cela répondrait parfaitement à ma question. : D TX! –
J'ai lu la documentation et il y a une jolie table qui explique clairement les interactions possibles entre un thread et le verrou. Je vous remercie. Cela semble être la réponse pour moi. –
@Jared - bien sûr, dans l'usage normal, mais pas de la façon dont l'OP l'a décrit - il veut que plusieurs ajouts/suppressions soient simultanés et que seuls les clones bloquent les lectures/écritures. –