创建线程

时间:2015-12-18 16:48:44

标签: c++ multithreading pthreads thread-synchronization

我正在尝试实现一个创建线程的类,递增一个值并将其发送到另一个线程,该数字定义为(value * value)%线程数

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdlib>
#include <vector>

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
volatile int counter = 0;
volatile int maxval = 0;
volatile int next = 0;

extern "C" void *func(void *p);

class Worker {
private:
    pthread_t thread = 0;
    int nth = 0;
    int nproc = 0;
public:
    Worker () {};
    Worker(int _nproc, int _nth) {
        nth = _nth;
        nproc = _nproc;
    };
    void start() {
        pthread_create(&thread, NULL, func, NULL); // Line 27

    };
    void wait() {
        while (nth != next) {
            pthread_cond_wait(&cv, &m);
        }
    };
    void notify() {
        pthread_cond_broadcast(&cv);
    };
    void run() {
        while (counter != maxval) {
            pthread_mutex_lock(&m);
            Worker::wait();
            if (counter != maxval) {
                printf("%d %d\n", nth, counter);
                ++counter;
            }
            next = (counter * counter) % nproc;
            Worker::notify();
            pthread_mutex_unlock(&m);
        }
    };
    void join() {
        pthread_join(thread, NULL);
    }
};

extern "C" void *func(void *p) {
    Worker *w = reinterpret_cast<Worker*>(p);
    w->run();
    return NULL;
}

int main(int argc, char *argv[]) {
    int nthreads = atoi(argv[1]);
    maxval = atoi(argv[2]);
    std::vector<Worker> workers;
    for (int i = 0; i != nthreads; ++i) {
        workers.push_back(Worker(nthreads, i));
    }
    for (int i = 0; i != workers.size(); ++i) {
        workers[i].start();
    }
    for (int i = 0; i != workers.size(); ++i) {
        workers[i].join();
    }
    return 0;
}

无法检查算法是否正确,因为当我调用 pthread_create (第27行)时出现分段错误

这就是gdb所说的:

#0  0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30
#1  0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40
#2  0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57
#3  0x00007ffff76296aa in start_thread (arg=0x7ffff6f4f700)
    at pthread_create.c:333
#4  0x00007ffff735eeed in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

有人能解释一下这个功能究竟发生了什么吗?我该如何正确实现?

非常感谢。

2 个答案:

答案 0 :(得分:2)

func没有处理NULL被传入,pthread_create的第四个参数是在第三个参数中发送函数的内容。

func更改为正确处理NULL,您应该做得很好:

extern "C" void *func(void *p) {
    if (NULL == p)
        return NULL;
    Worker *w = reinterpret_cast<Worker*>(p);
    w->run();
    return NULL;
}

另外,+1用于发布gdb输出,所以这里有更多信息:

如果我们向上跟踪您的堆栈跟踪(我按照它们发生的顺序键入它们),我们会看到func在runWorker转换NULL时执行了转换和(p=0x0)的工作。 1}}。请注意(this=0x0)#2 0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57 #1 0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40

Worker::run

counter工作正常,因为它只能在访问maxval之前访问mWorker::wait()#0 0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30

Worker::wait()

nth中,您正在访问Worker,它是null $('#SelectID').change(function(){ $.ajax({ type: "POST", url: "../example.php", data: "{selectedvalue: " + $(this).val() + "}", contentType: "application/x-www-form-urlencoded; charset=UTF-8", success: function(result){ $('#div').html(result); } }); }); 实例的成员,您最终会获得段错误。

答案 1 :(得分:2)

问题是在创建线程时,您正在为最后一个参数传递NULL

pthread_create(&thread, NULL, func, NULL);

线程启动时,会调用 func() 并传递NULL值。 因此,在 func() pNULL ,您正在尝试投射然后访问该内存位置。这就是你得到分段错误的原因。