Я написал многопоточную тестовую программу для тестирования моего сервера БД, но похоже, что я столкнулся с каким-то сценарием состояния гонки / неопределенного поведения.
Моя программа использует 'n'
количество потоков для ввода 'x'
количество записей (IMSI) в базе данных. В потоках я выбираю значение IMSI (для ввода в БД), а затем вызываю API, который вставляет IMSI в БД. Хотя я не получаю никаких ошибок в API «Вставка», тем не менее, не все IMSI вставляются в БД!
Вот программа:
#include"DB.hpp"
#include<thread>
#include<vector>
#include<string>
#include<mutex>
#include<algorithm>
#include<iostream>
using namespace std;
std::mutex mtx_imsi;
std::mutex mtx_errorCount;
std::mutex mtx_addImsi;
class data
{
public:
static int64_t imsi; //This is stored in the DB
static int64_t no_of_threads;
static int64_t no_of_subscribers; //No. of Imsis that will be stored.
static int64_t error_count; //No. of IMSIs which couldn't be written.
static vector<string> imsi_list;
static void get_imsi(int64_t &l_imsi)
{
std::lock_guard<mutex> lg(mtx_imsi);
if(imsi==405862999999999+no_of_subscribers)
l_imsi=-1;
else
l_imsi=++imsi;
}
static void add_count(int64_t l_count)
{
std::lock_guard<mutex> lg(mtx_errorCount);
error_count+=l_count;
}
static void add_imsi(vector<string>& list)
{
std::lock_guard<mutex> lg(mtx_addImsi);
for(const auto& x:list)
imsi_list.push_back(x);
}
};
int64_t data::imsi(405862999999999); //This is the initial value
int64_t data::no_of_threads;
int64_t data::no_of_subscribers;
int64_t data::error_count=0;
vector<string> data::imsi_list;
int main(int argc, char* argv[])
{
if(argc!=3)
{
cout<<endl<<"Error in input parameters"<<endl;
cout<<endl<<argv[0]<<"[No_of_threads] [No_of_subscribers] [NODE_IP]"<<endl;
cout<<"e.g. "<<argv[0]<<"10 200000 10.32.129.66"<<endl;
exit(-1);
}
data::no_of_threads=stoi(argv[1]);
data::no_of_subscribers=stoi(argv[2]);
DB::InitDBConnection(argv[3]); //This will initialise the DB connection with the IP
vector<thread> t;
for(int i=0;i<data::no_of_threads;i++)
{
thread th([&]{
int64_t errorCount=0,temp_imsi;
vector<string> temp_list;
data::get_imsi(temp_imsi);
while(temp_imsi!=-1)
{
string l_imsi=to_string(temp_imsi);
temp_list.push_back(l_imsi);
ReturnCode status=DB::rtInsertImsi(l_imsi);
if(status!=INSERT_OK)
++errorCount;
data::get_imsi(temp_imsi);
}
data::add_count(errorCount);
data::add_imsi(temp_list);
});
t.push_back(move(th));
}
for(auto &x:t)
x.join();
std::sort (data::imsi_list.begin(), data::imsi_list.end());
cout<<endl<<"IMSI LIST"<<endl;
// Printing the IMSIs which were entered.
for(const auto&x:data::imsi_list)
cout<<x<<endl;
cout<<endl<<"Number of Imsis used: "<<data::imsi-405862999999999;
cout<<endl<<"Number of errors: "<<data::error_count;
return 0;
}
В данный момент я считаю, что в моей функции «Вставка» (которую я вызываю внутри потока) нет ничего плохого, потому что она используется в других многопоточных программах без такого поведения. Что может быть причиной того, что некоторые IMSI не были вставлены? Что-то не так с этой основной программой?
Во время публикации этого вопроса я изменил реальный код, чтобы сделать код более понятным (я не знал, что буду удалять строки, содержащие ошибку). Теперь я осознал свою ошибку. В моем реальном коде я не передаю Imsi, полученный из get_imsi (), в мою функцию вставки (которая была бы поточно-ориентированной), вместо этого я использую полученное значение, чтобы заполнить структуру данных и передать эту структуру данных вставке функция. Поскольку я не заполнял структуру данных потокобезопасным способом, я получил замечания, о которых упомянул.
Я хочу удалить вопрос, но из-за запущенной награды я больше не могу это делать!