简体   繁体   English

Lamport的Bakery算法的实现具有1个以上线程的段错误

[英]Implementation of Lamport's Bakery Algorithm has seg faults with more than 1 thread

I'm implementing Lamport's Bakery Algorithm using pthreads and a Processor class to act as shared memory. 我正在使用pthreads和Processor类来实现Lamport的Bakery算法,以充当共享内存。 With a single thread it works fine, with 2 threads I get the seg fault after thread 2 runs through all 30 attempts to access the 'bakery': 使用单个线程,它可以正常工作,使用2个线程,在线程2经过30次尝试访问“面包房”的所有尝试后,我遇到了seg错误:

dl-tls.c: No such file or directory. dl-tls.c:没有这样的文件或目录。

With 3 or more threads I get the seg fault after outputting "here" twice from the bakeryAlgo function: 使用3个或更多线程时,从akerysterAlgo函数两次输出“ here”后,出现段错误:

0x0804ae52 in Processor::getNumber (this=0x5b18c483) at Processor.cpp:33 Processor.cpp:33上Processor :: getNumber(this = 0x5b18c483)中的0x0804ae52

bakery.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;
}

The code in Processor.cpp / Processor.h is simple, it's just a few getters and setters on the values id, choosing, and number, with a default constructor and a constructor that takes an int id. Processor.cpp / Processor.h中的代码很简单,它只是关于值id,选择和数字的一些获取器和设置器,具有默认构造函数和采用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;
}

Does anyone have any idea why these seg faults are occuring? 有谁知道为什么发生这些段错误? The places gdb says they are occuring look like innocent lines of code to me. gdb表示发生的位置对我而言似乎是无辜的代码行。

Are you using a pointer to a vector defined in main as your data? 您是否正在使用指向main定义的vector的指针作为数据? Stack is not shared among threads, so the other threads accessing this memory would be undefined behavior at best. 堆栈未在线程之间共享,因此访问该内存的其他线程充其量是未定义的行为。 I expect this is the source of your troubles. 我希望这是您麻烦的根源。

You are taking the address of an element in a vector which is changing: 您正在改变的向量中获取元素的地址:

    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));
    }

Each time a new thread is pushed onto the threads vector , the vector may be relocated in memory, so the pointer that you passed to pthread_create may be pointing to garbage when the next thread is added. 每次将新线程推入threads vector ,该向量都可能会在内存中重新定位,因此当添加下一个线程时,传递给pthread_create的指针可能指向垃圾。

You want to do this instead: 您要改为执行此操作:

    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));
    }

By waiting until all the elements are added to the vector before you create your threads, you are now passing pointers that stay good while the threads are running. 通过在创建线程之前等待所有元素都添加到向量中,现在可以传递在线程运行时保持良好状态的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM