使用传递给线程

时间:2018-06-13 00:50:41

标签: c multithreading

我正在学习C语言中的并发性。我知道有几种方法可以初始化pthread_mutex_t。

这个简单的程序运行良好:

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void* worker(void* arg) {

    pthread_mutex_lock(&lock); 
    printf("worker says hi\n");
    pthread_mutex_unlock(&lock);

    return NULL;
}

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

    pthread_t p;
    pthread_create(&p, NULL, worker, NULL);

    pthread_mutex_lock(&lock);
    printf("master says hi\n");
    pthread_mutex_unlock(&lock);

    pthread_join(p, NULL);

    return 0;
}

但是,如果我不希望全局定义锁,我认为我可以在主线程中定义它并将其传递给另一个线程,如下所示:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* worker(void* arg) {
    pthread_mutex_t lock = * (pthread_mutex_t *) arg;

    pthread_mutex_lock(&lock);
    printf("worker says hi\n");
    pthread_mutex_unlock(&lock);

    return NULL;
}

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

    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    pthread_t p;
    pthread_create(&p, NULL, worker, &lock);

    pthread_mutex_lock(&lock);
    printf("master says hi\n");
    pthread_mutex_unlock(&lock);

    pthread_join(p, NULL);

    return 0;
}

然而,这工作。相反,它只打印master says hi并挂起。

我认为这可能是死锁,所以我将一些睡眠时间插入主人,如下所示:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* worker(void* arg) {
    pthread_mutex_t lock = * (pthread_mutex_t *) arg;

    pthread_mutex_lock(&lock);
    printf("worker says hi\n");
    pthread_mutex_unlock(&lock);

    return NULL;
}

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

    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    pthread_t p;
    pthread_create(&p, NULL, worker, &lock);

    sleep(1);

    pthread_mutex_lock(&lock);
    printf("master says hi\n");
    pthread_mutex_unlock(&lock);

    pthread_join(p, NULL);

    return 0;
}

正如预期的那样,这打印出worker says hi,然后在一秒之后打印master says hi

但是,如果我将睡眠移动到工作人员,如下所示,它会再次挂起:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* worker(void* arg) {
    pthread_mutex_t lock = * (pthread_mutex_t *) arg;

    sleep(1);

    pthread_mutex_lock(&lock);
    printf("worker says hi\n");
    pthread_mutex_unlock(&lock);

    return NULL;
}

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

    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    pthread_t p;
    pthread_create(&p, NULL, worker, &lock);

    pthread_mutex_lock(&lock);
    printf("master says hi\n");
    pthread_mutex_unlock(&lock);

    pthread_join(p, NULL);

    return 0;
}

如果我将睡眠功能置于行<{1}}之上,那么不会挂起。我不确定如何解释这种行为。

2 个答案:

答案 0 :(得分:3)

worker函数正在制作互斥锁的副本,它应该只使用现有的互斥锁。修复是将lock变量声明为指向互斥锁的指针:

void* worker(void* arg) {

    pthread_mutex_t *lock = arg;

    pthread_mutex_lock(lock);
    printf("worker says hi\n");
    pthread_mutex_unlock(lock);

    return NULL;
}

答案 1 :(得分:3)

我复制并粘贴了您的所有示例,而不是一个被绞死或显示您的行为。

我不太确定,但我认为问题出在这里的线程函数中:

pthread_mutex_t lock = * (pthread_mutex_t *) arg;

这会创建原始互斥锁的按位副本,具体取决于内容 结构,这可能会导致你看到的问题。因此,glibc + pthreads的不同实现/版本可能会产生不同的结果。

我总是将我的锁作为参数传递给线程,但我没有 问题,但是我没有创建锁的副本,所以我试试这个:

void* worker(void* arg) {
    pthread_mutex_t *lock = arg;

    pthread_mutex_lock(lock);
    printf("worker says hi\n");
    pthread_mutex_unlock(lock);

    return NULL;
}

这可以解决你的问题。