Я хотел бы, чтобы потоки добавляли уникальные числа с плавающей точкой в список, и сначала подумал о приближении к нему, вставив в unordered_map<float,int>
, где значения не имеют значения (по сути, это unordered_set<float>
). Потоки могут перекрывать друг друга значениями 1 в том же ключе, ie. не имеет значения, если поток 1 сначала записал значение 1 или поток 2, потому что в конце он просто будет равен 1. Таким образом, гонки данных должны быть неактуальными.
#include <iostream>
#include <string>
#include <unordered_set>
#include <thread>
#include <set>
std::unordered_set<float> mySet;
void someTask(int i) {
mySet.insert(i % 3);
}
int main()
{
std::thread threads[8];
for (int i = 0; i < 8; i++) {
threads[i] = std::thread(someTask, i);
}
for (int i = 0; i < 8; i++) {
threads[i].join();
}
for (auto const& mySetVal : mySet) {
std::cout << mySetVal << std::endl; // Oddly, mySet might have duplicates
}
std::set<float> mySet_( mySet.begin(), mySet.end() ); // Make a new ordered set, and removing duplicates along the way
for (auto const& mySetVal : mySet_) {
std::cout << mySetVal << std::endl; // Would this always produce the expected result of 0,1,2?
}
}
Однако mySet, несмотря на то, что он является unordered_set
, имеет дубликаты, и я предполагаю, что это связано с состоянием гонки во время чтения для ключа, и в итоге мы вставили дважды? Но когда я заменяю mySet на unordered_map<float,int>
, все равно остаются дубликаты - я бы подумал, даже если есть условие гонки, и хотя мы не можем гарантировать, какой поток будет выполняться первым, в конце потоки могут переопределить друг друга без какого-либо вреда.
Так почему же есть дубликаты?
И, удалив дубликаты в конце, это потокобезопасно, или это даст ожидаемые результаты 0,1 , 2 последовательно / надежно? Если нет, то поточно-ориентированное решение для кода выше было бы здорово!