3

我不明白为什么我的代码会给我疯狂的输出,有时还会出现段错误(代码是由我编写的 08218722 以防万一我的大学检查抄袭)。

该代码在Linux Mint 14 中用C++编写,并使用

g++ -o code.exe code.cpp -lpthread

然后运行./code.exe​​.

该代码应该生成一个随机字符向量(仅使用字符 a、b、c、d、e 和 f),最多 1000000,然后循环并计算每个字符的数量。这在我添加线程之前工作正常(测试非线程和线程之间的运行时间的分配的一部分)。所以我创建了 1000 个线程,它们被告知要添加 1000 个字符以添加到向量中。我在这里做错了什么?

更新 - 代码仍然输出一些疯狂的结果 - 现在它不显示字符而是某种方块

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <vector>
#include <algorithm>
#include <pthread.h>
#include <ctime>

using namespace std;

//Variable Declarations
const int length = 1000000; // length
const int packets = 1000; // packets length
const char chars[6] = {'a', 'b', 'c', 'd', 'e', 'f'}; // chars to choose
vector<char> charList(length); //vector of random charecter list
int charGroup[6] = {}; //stores char count
pthread_t threads[packets];



//Structure Declarations
struct dataStruct {
    int start;
    int end;
};

//Function Declarations
void *randomLetterGenerator(void * args); // Declaring function

// prints the vector
void outVector(char n)
{
    cout << n;
}

void GroupVector(char n)
{
   charGroup[n] = charGroup[n] + 1;
}

int main(){
        cout << "Creating a Random Char Array" << endl;
        cout << "using only letters ranging between a and f." << endl;
        //srand(time(NULL)); // sets the time seed
        clock_t start = clock();
        for(int i=0;i<length/packets;i++) {
            printf("\rPlease wait...%3d/%3d",i*packets,length);
            //Created in packets
            dataStruct ds;
            ds.start = i * (length/packets);
            ds.end = ds.start + (length/packets);
            pthread_create(&threads[i], NULL, randomLetterGenerator, (void *)&ds);
        }

        for(int i=0;i<length/packets;i++) {
            pthread_join(threads[i], NULL);
        }

        printf("\n"); //new line

        //prints out the new char list

        for_each(charList.begin(), charList.end(), outVector) ;

        printf("\n"); //new line

        //Counts and places in the correct array
        for_each(charList.begin(), charList.end(), GroupVector) ;

        int total = 0;

        for (int i = 0; i < 6; i++) {
            total += charGroup[chars[i]];
            cout << chars[i] << " = " << charGroup[chars[i]] << endl;
        }
        cout << "\nTotal: " << total << endl;
        clock_t ends = clock();
        cout << "Run Time :"
        << (double) (ends - start) / CLOCKS_PER_SEC << endl;
         pthread_exit(NULL);    
        return 0;   

}

void * randomLetterGenerator(void * datastruct){
    dataStruct ds = *((dataStruct *) datastruct);
    int start = ds.start;
    int end = ds.end;

     srand( time(NULL) );
    for(unsigned int c=start;c<end;c++){
        int i = (int) (rand() % 6);
        char rchar = chars[i];
        //--pthread_mutex_lock (&mutex);
        charList.at(c)= i;
        //--charList.push_back(rchar);  
        //--pthread_mutex_unlock (&mutex);  
    }
    pthread_exit(NULL);

}
4

2 回答 2

3

很可能是因为您没有锁定。多个线程不能同时写入向量之类的标准容器。charList.push_back(rchar);当您的函数中有多个线程在执行时randomLetterGenerator,这正是您正在执行的操作。您需要用 包围此代码mutex,例如:

pthread_mutex_t mutex;

void * randomLetterGenerator(void * datastruct)
{ 
    //Code as before
    //...
    //Lock the mutex
    charList.push_back(rchar);
    //Unlock the mutex
}
于 2013-01-04T03:32:34.603 回答
3

您在这里使用了错误的方法。您需要创建一个大小合适的向量,然后使用元素分配将元素填充到其中。

使用向量的push_back函数将不起作用,并且可能会使您的程序崩溃,因为它必须修改向量的内部状态,这不是线程安全的。如果你通过互斥锁将它包围起来,它会工作得很好,但是你会完全放弃并行性的任何好处。

因此,创建一个已经具有所需条目数的向量 ( vector<char> lots_of_chars(length);),然后使用项目分配来分配给每个项目。每个线程都必须从向量的不同偏移量开始,这样它们就不会互相踩踏。

我会给你具体的代码来完成这项工作,但这听起来像是一项任务,所以我想我会让你自己解决。

还有另一个线程安全问题。它实际上可能不会在这里引起任何问题,但您应该意识到这一点。rand不是线程安全的。它依赖于共享全局状态来生成连续的“随机”数字。除非您使用 boost 或 C++11,否则我知道没有一个好的线程安全随机数生成选项。如果你有 C++11,你应该使用 C++11s 内置的线程支持而不是 pthreads。

In this particular case, it's not terribly important that the random number generation actually generate random numbers. So if threads stomp on each other through the random number generator and cause it to repeat states and generate the same sequences of random numbers or whatever, that should be OK. Of course, that's just the most likely outcome. Using rand in this non-thread-safe way is actually undefined behavior and anything at all might happen because of it.

于 2013-01-04T03:37:19.147 回答