使用向量和 pthreads 的不一致计数
Inconsistent Tally Using vectors and pthreads
所以我正在开发一个简单的程序来计算来自多个文本文件的选票(每个文件的每一行包含其中一位候选人的姓名,代表一票)。
我大部分时间都在工作,还有一个问题:每位候选人的总票数对于给定的候选人来说是不准确的,除非该候选人在每个[=41]中的票数完全相同=] votes.txt
文件。顺序没有区别。
例如:如果votes1.txt
是目标目录中的唯一文件,并且每个候选人都有1票:
votes1.txt:
Clinton
Cruz
Kasich
Sanders
Trump
每次我 运行 程序产生的最终计数将正确地有 1 票。
类似地,如果目标目录有 votes1.txt
和 votes2.txt
并且每个候选人都有 1 票(以任何顺序),最终计票将正确地为每个候选人 2 票。
然而,一旦文本文件开始对候选人获得不同数量的选票,我就会在最终计票中得到不正确和不一致的总数。
EG:如果votes1.txt
和votes2.txt
的内容如下:
votes1.txt:
Clinton
Cruz
Kasich
Sanders
Trump
votes2.txt:
Clinton
Cruz
Kasich
Clinton
Sanders
Trump
克林顿的最终统计结果将不正确(在这种情况下,它仍然是 2 个而不是 3 个)。但是,如果这些文件都为克林顿投了 2 票,那么最终的统计结果将再次正确,克林顿总共有 4 票,其余各有 2 票。 votes.txt
文件越大,越不一致,最终总数只会越来越离谱。
这是一个非常奇怪且具体的错误,但通过我的代码梳理我无法查明是什么导致了它。
相关代码如下:
int main(int argc, char *argv[])
{
vector<string> voteTallyFiles;
vector<voteTally> intermVoteTallies;
voteTally finalVoteTally;
string args;
voteTally returnValue;
void *returnValueP;
void *argp;
int index = 0;
//Grab vote tally files from Target Directory
getFileNames(voteTallyFiles);
vector<pthread_t> threads(voteTallyFiles.size());
//Count the votes using pthreads and a thread function
for (vector<pthread_t>::iterator iter = threads.begin(); iter != threads.end(); ++iter, index++)
{
args = voteTallyFiles[index];
argp = &args;
pthread_create(&*iter, NULL, &countVotes, argp);
}
// Wait for the threads
for (vector<pthread_t>::iterator iter = threads.begin(); iter != threads.end(); ++iter)
{
pthread_join(*iter, &returnValueP);
returnValue = *((voteTally*)returnValueP);
intermVoteTallies.push_back(returnValue);
}
// Aggregate sub-tallies
for (unsigned int i = 0; i < intermVoteTallies.size(); i++)
{
finalVoteTally.pres1 += intermVoteTallies[i].pres1;
finalVoteTally.pres2 += intermVoteTallies[i].pres2;
finalVoteTally.pres3 += intermVoteTallies[i].pres3;
finalVoteTally.pres4 += intermVoteTallies[i].pres4;
finalVoteTally.pres5 += intermVoteTallies[i].pres5;
}
return 0;
}
void* countVotes(void *argp)
{
string* actualArgs = (string*)argp;
string fileName = *actualArgs;
string line;
ifstream inFile;
voteTally *subTally = new voteTally;
inFile.open(fileName.c_str());
while (getline(inFile, line))
{
if (line == PRES1)
{
subTally->pres1++;
}
else if (line == PRES2)
{
subTally->pres2++;
}
else if (line == PRES3)
{
subTally->pres3++;
}
else if (line == PRES4)
{
subTally->pres4++;
}
else if (line == PRES5)
{
subTally->pres5++;
}
}
return subTally;
}
这是一个问题:
args = voteTallyFiles[index];
argp = &args;
pthread_create(&*iter, NULL, &countVotes, argp);
在上面的行中,您将 argp
传递给线程,但它们都指向完全相同的局部变量 args
,这意味着所有线程可能使用相同的数据。
而是使用寻址运算符将指针传递给 voteTallyFiles[index]
:
pthread_create(&*iter, NULL, &countVotes, &voteTallyFiles[index]);
所以我正在开发一个简单的程序来计算来自多个文本文件的选票(每个文件的每一行包含其中一位候选人的姓名,代表一票)。
我大部分时间都在工作,还有一个问题:每位候选人的总票数对于给定的候选人来说是不准确的,除非该候选人在每个[=41]中的票数完全相同=] votes.txt
文件。顺序没有区别。
例如:如果votes1.txt
是目标目录中的唯一文件,并且每个候选人都有1票:
votes1.txt:
Clinton
Cruz
Kasich
Sanders
Trump
每次我 运行 程序产生的最终计数将正确地有 1 票。
类似地,如果目标目录有 votes1.txt
和 votes2.txt
并且每个候选人都有 1 票(以任何顺序),最终计票将正确地为每个候选人 2 票。
然而,一旦文本文件开始对候选人获得不同数量的选票,我就会在最终计票中得到不正确和不一致的总数。
EG:如果votes1.txt
和votes2.txt
的内容如下:
votes1.txt:
Clinton
Cruz
Kasich
Sanders
Trump
votes2.txt:
Clinton
Cruz
Kasich
Clinton
Sanders
Trump
克林顿的最终统计结果将不正确(在这种情况下,它仍然是 2 个而不是 3 个)。但是,如果这些文件都为克林顿投了 2 票,那么最终的统计结果将再次正确,克林顿总共有 4 票,其余各有 2 票。 votes.txt
文件越大,越不一致,最终总数只会越来越离谱。
这是一个非常奇怪且具体的错误,但通过我的代码梳理我无法查明是什么导致了它。
相关代码如下:
int main(int argc, char *argv[])
{
vector<string> voteTallyFiles;
vector<voteTally> intermVoteTallies;
voteTally finalVoteTally;
string args;
voteTally returnValue;
void *returnValueP;
void *argp;
int index = 0;
//Grab vote tally files from Target Directory
getFileNames(voteTallyFiles);
vector<pthread_t> threads(voteTallyFiles.size());
//Count the votes using pthreads and a thread function
for (vector<pthread_t>::iterator iter = threads.begin(); iter != threads.end(); ++iter, index++)
{
args = voteTallyFiles[index];
argp = &args;
pthread_create(&*iter, NULL, &countVotes, argp);
}
// Wait for the threads
for (vector<pthread_t>::iterator iter = threads.begin(); iter != threads.end(); ++iter)
{
pthread_join(*iter, &returnValueP);
returnValue = *((voteTally*)returnValueP);
intermVoteTallies.push_back(returnValue);
}
// Aggregate sub-tallies
for (unsigned int i = 0; i < intermVoteTallies.size(); i++)
{
finalVoteTally.pres1 += intermVoteTallies[i].pres1;
finalVoteTally.pres2 += intermVoteTallies[i].pres2;
finalVoteTally.pres3 += intermVoteTallies[i].pres3;
finalVoteTally.pres4 += intermVoteTallies[i].pres4;
finalVoteTally.pres5 += intermVoteTallies[i].pres5;
}
return 0;
}
void* countVotes(void *argp)
{
string* actualArgs = (string*)argp;
string fileName = *actualArgs;
string line;
ifstream inFile;
voteTally *subTally = new voteTally;
inFile.open(fileName.c_str());
while (getline(inFile, line))
{
if (line == PRES1)
{
subTally->pres1++;
}
else if (line == PRES2)
{
subTally->pres2++;
}
else if (line == PRES3)
{
subTally->pres3++;
}
else if (line == PRES4)
{
subTally->pres4++;
}
else if (line == PRES5)
{
subTally->pres5++;
}
}
return subTally;
}
这是一个问题:
args = voteTallyFiles[index];
argp = &args;
pthread_create(&*iter, NULL, &countVotes, argp);
在上面的行中,您将 argp
传递给线程,但它们都指向完全相同的局部变量 args
,这意味着所有线程可能使用相同的数据。
而是使用寻址运算符将指针传递给 voteTallyFiles[index]
:
pthread_create(&*iter, NULL, &countVotes, &voteTallyFiles[index]);