-1

pthreads と Processor クラスを使用して共有メモリとして機能する Lamport's Bakery Algorithm を実装しています。単一のスレッドでは正常に動作し、2 つのスレッドでは、スレッド 2 が「ベーカリー」への 30 回のアクセス試行すべてを実行した後、セグ フォールトが発生します。

dl-tls.c: そのようなファイルまたはディレクトリはありません。

スレッドが 3 つ以上ある場合、bakeryAlgo 関数から「here」を 2 回出力した後、セグ フォールトが発生します。

Processor::getNumber の 0x0804ae52 (this=0x5b18c483)、Processor.cpp:33 で

ベーカリー.cpp

struct argStruct {
    vector<Processor>* processors;
    Processor* processor;
};

int findMax(vector<Processor>* processors) {
    int max = -99;
    for (int i = 0; i < processors->size(); i++) {
        if (processors->at(i).getNumber() > max) {
            max = processors->at(i).getNumber();
        }
    }
    return max;
}

void* bakeryAlgo(void* arg) {
    struct argStruct* args = static_cast<struct argStruct *>(arg);
    cout << "here" << endl;
    for (int i = 0; i < 30; i++) {
        args->processor->setChoosing(1);
        args->processor->setNumber(findMax(args->processors));
        args->processor->setChoosing(0);
        for (int j = 0; j < args->processors->size(); j++) {
            int jChoosing = args->processors->at(j).getChoosing();
            int jNumber = args->processors->at(j).getNumber();
            int jId = args->processors->at(j).getId();
            int pNumber = args->processor->getNumber();
            int pId = args->processor->getId();
            if (jId != pId) {
                while (jChoosing != 0) {}
                while (jNumber != 0 && ((jNumber < pNumber) || ((jNumber == pNumber) && (jId < pId)))) { }
            }
        }
        cout << "Processor: " << args->processor->getId() << " executing critical section!" << endl;
        args->processor->setNumber(0);
    }
}

int main(int argc, char *argv[]) {

    // Check that a command line argument was provided
    if (2 == argc) {
        int numProcessors = atoi(argv[1]);
        vector<Processor> processors;
        vector<argStruct> argVect;
        vector < pthread_t > threads;
        for (int i = 0; i < numProcessors; i++) {
            Processor p = Processor(i);
            processors.push_back(p);
        }
        for (int i = 0; i < numProcessors; i++) {
            pthread_t processorThread;
            struct argStruct args;
            args.processors = &processors;
            args.processor = &processors.at(i);
            argVect.push_back(args);
            threads.push_back(processorThread);
            pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
        }
        for (int i = 0; i < numProcessors; i++) {
            pthread_join(threads.at(i), NULL);
        }
    } 
    else {
        cout << "Usage: bakery num, num is number of threads." << endl;
    }
    return 0;
}

Processor.cpp / Processor.h のコードは単純です。id、choose、number の値に対する getter と setter がいくつかあり、デフォルトのコンストラクタと int id を取るコンストラクタがあります。

Processor::Processor() {

}

Processor::Processor(int idval) {
    id = idval;
    choosing = 0;
    number = 0;
}

Processor::~Processor() {

}

int Processor::getChoosing() {
    return choosing;
}

int Processor::getNumber() {
    return number;
}

int Processor::getId() {
    return id;
}

void Processor::setChoosing(int c) {
    choosing = c;
}

void Processor::setNumber(int n) {
    number = n;
}

これらのセグ障害が発生している理由を知っている人はいますか? gdb が発生していると言う場所は、私には無害なコード行のように見えます。

4

2 に答える 2

2

vectorデータとして定義済みへのポインタを使用してmainいますか? スタックはスレッド間で共有されないため、このメモリにアクセスする他のスレッドはせいぜい未定義の動作になります。これがあなたの悩みの元だと思います。

于 2013-01-21T06:15:58.220 に答える
0

変化しているベクトル内の要素のアドレスを取得しています。

    for (int i = 0; i < numProcessors; i++) {
        pthread_t processorThread;
        struct argStruct args;
        args.processors = &processors;
        args.processor = &processors.at(i);
        argVect.push_back(args);
        threads.push_back(processorThread);

        // danger! 
        pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
    }

新しいスレッドがにプッシュされるたびthreads vectorに、ベクトルがメモリ内に再配置される可能性があるため、pthread_createに渡したポインタは、次のスレッドが追加されたときにガベージを指している可能性があります。

代わりにこれを実行します。

    for (int i = 0; i < numProcessors; i++) {
        pthread_t processorThread;
        struct argStruct args;
        args.processors = &processors;
        args.processor = &processors.at(i);
        argVect.push_back(args);
        threads.push_back(processorThread);
    }
    for (int i = 0; i < numProcessors; i++) {
        pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
    }

スレッドを作成する前にすべての要素がベクターに追加されるまで待つことで、スレッドの実行中に良好な状態を維持するポインターを渡すことになります。

于 2013-01-21T06:22:16.203 に答える