9
votes

Est-ce que STL vide () est en sécurité?

J'ai plusieurs threads modifiant un vecteur stl et une liste de stl.
Je veux éviter de devoir prendre un verrou si le conteneur est vide

le code suivant serait-il threadsafe? Et si les articles étaient une liste ou une carte? xxx


1 commentaires

Merci pour les réponses. Pour clarifier la question: un autre thread va ajouter aux éléments. Aucun autre thread ne retirera des éléments - supplies ne se produira qu'à l'intérieur de Dostuffwithitems () et seulement un seul appels de threads Dostuff (). C'est bon si les articles.empty () renvoie false alors qu'un autre fil y ajoutent. Ce n'est pas correct si les articles.empty () provoque une crash de l'application si un autre thread y ajoutant


5 Réponses :


2
votes

stl n'est pas le fil sûr et vide aussi. Si vous souhaitez faire du coffre-fort, vous devez fermer toutes ses méthodes par mutex ou autre synchronisation


0 commentaires

4
votes

Il n'y a pas de garantie de fil-sécurité sur quoi que ce soit dans les conteneurs et les algorithmes de la STL.

Alors, non.


0 commentaires

2
votes

Indépendamment de la sécurité vide ou non du fil de sécurité, votre code ne sera pas, comme écrit, accomplir votre objectif.

class A  
{  
    vector<int> items  
    void DoStuff()  
    {  
        if(!items.empty())  
        {  
            //Another thread deletes items here.
            AquireLock();  
            DoStuffWithItems();  
            ReleaseLock();  
        }  
     }  
}  


2 commentaires

Votre point (// Un autre thread supprime les éléments ici.) Est clair. Pourtant, il est également évident que vous pouvez vérifier vide () après avoir acquis la serrure pour être sûr.


@skwllSP: un point valide. Si vide () est le fil de sécurité, vérifiez d'abord à vide, le verrouillage, puis la revérisation peut éviter un verrou inutile.



6
votes

Cela dépend de ce que vous attendez. Les autres réponses sont correctes que en général , les conteneurs standard C ++ ne sont pas thread-coffre-fort et que en particulier votre code ne protège pas contre un autre fil modifiant le conteneur entre votre appel à vide et l'acquisition du verrou (mais cette question n'est pas liée à la sécurité du thread de vecteur :: vide ).

Donc, pour préserver les malentendus: Votre code ne garantit pas éléments ne sera pas vide à l'intérieur du bloc.

Mais votre code peut toujours être utile, car tout ce que vous voulez faire est d'éviter les créations de verrouillage redondantes. Votre code ne donne pas de garanties mais il peut empêcher une création de verrouillage inutile. Cela ne fonctionnera pas dans tous les cas (les autres threads peuvent toujours vider le conteneur entre votre chèque et votre verrou) mais dans certains cas . Et si tout ce que vous avez après est une optimisation en omettant une serrure redondante, votre code accomplit cet objectif.

Assurez-vous simplement que tout accès au conteneur est protégé par des serrures.

Au fait, ce qui précède est Strictement parler comportement indéfini : une implémentation stl est théoriquement autorisée à modifier Mubble Membres à l'intérieur de l'appel vide . Cela signifierait que l'appelait apparemment inoffensif (parce que la lecture seule) à vide peut causer réellement un conflit. Malheureusement, vous ne peut pas s'appuyer sur l'hypothèse que les appels en lecture seule sont en sécurité avec des conteneurs STL.

En pratique, cependant, je suis sûr que vecteur :: vide pas modifie les membres . Mais déjà pour Liste :: vide Je suis moins sûr. Si vous voulez vraiment les garanties , alors verrouillez-la tous les l'accès ou n'utilisez pas les conteneurs STL.


0 commentaires

1
votes

Comme il est déjà répondu, le code ci-dessus n'est pas le fil sûr et le verrouillage est obligatoire avant de faire quoi que ce soit avec le conteneur. Mais ce qui suit devrait avoir une meilleure performance que de toujours verrouiller et je ne peux penser à une raison pour laquelle il peut être dangereux. L'idée ici est que le verrouillage peut être coûteux et nous l'évigeons, chaque fois que cela n'était pas vraiment nécessaire.

class A
{
    vector<int> items;  
    void DoStuff()  
    {  
        if(!items.empty())  
        {  
            AquireLock();
            if(!items.empty())
            {
                DoStuffWithItems();  
            }
            ReleaseLock();  
        }
     }
 }  


0 commentaires