web-dev-qa-db-fra.com

incrément atomique et compteur de retour

Essayer de créer une fonction de génération d'ID unique, et j'ai trouvé ceci:

std::atomic<int> id{0};
int create_id() {
    id++;
    return id.load();
}

Mais je suppose qu'il est possible que cette fonction renvoie deux fois la même valeur, non? Par exemple, le thread A appelle la fonction, incrémente la valeur, puis s'arrête pendant que le thread B entre et incrémente également la valeur, enfin A et B renvoient tous les deux la même valeur.

Donc, en utilisant des mutex, la fonction pourrait ressembler à ceci:

std::mutex mx;
int id = 0;
int create_id() {
    std::lock_guard<std::mutex> lock{mx};
    return id++;
}

Ma question: est-il possible de créer le comportement d'apparition de valeurs int uniques à partir d'un compteur en utilisant uniquement de l'énergie atomique? La raison pour laquelle je demande, c'est parce que j'ai besoin de générer beaucoup d'identifiants, mais lisez que le mutex est lent.

16
Anonymous Entity

Utilisez simplement:

std::atomic<int> id;

int create_id() {
    return id++;
}

Voir http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith

30
Jarod42

Vos deux extraits de code font deux choses différentes.

id++;
return id.load();

ce code incrémente id, puis renvoie la valeur incrémentée.

std::lock_guard<std::mutex> lock{mx};
return id++;

ce code renvoie la valeur avant l'incrément.

Le code correct pour faire ce que le premier essaie de faire est

return ++id;

Le bon code pour faire ce que fait le second est

return id++;
6
Pete Becker