【发布时间】:2022-01-19 14:26:27
【问题描述】:
我在启动多个线程的程序中使用了锁 (pthread_mutex_t),所有线程都会收到一个指向结构的指针,该结构包含指向该互斥锁的指针。
所以有一个已初始化的互斥体,所有结构都有一个指向它的指针,但它不能很好地工作,我不明白为什么?
这里是一些示例代码,我尽量减少它。
让我们调用我的程序duck:
duck.c
# include "duck.h"
void *exec_threads(void *arg)
{
struct s_duck *duck;
duck = (struct s_duck*)arg;
pthread_mutex_lock(duck->mutex);
printf("duck nbr %i\n", duck->n);
pthread_mutex_unlock(duck->mutex);
return (NULL);
}
int main(void)
{
pthread_t *id;
pthread_mutex_t *mutex;
struct s_duck *duck;
int n;
int i;
n = 5; // number of threads
id = malloc(sizeof(int) * n); // allocate id[n]
mutex = malloc(sizeof(pthread_mutex_t)); // allocate mutex
pthread_mutex_init(mutex, NULL); // init mutex
duck = init_chain_ducks(mutex, n); // create chained list of structure
i = 0;
while (i < n)
{
pthread_create(&id[i], NULL, &exec_threads, duck); // launch threads
duck = duck->next;
i++;
}
i = 0;
while (i < n)
{
pthread_join(id[i], NULL); // join threads
i++;
}
write(1, "the end\n", 8);
return (0);
}
duck_chain.c
# include "duck.h"
struct s_duck *init_chain_ducks(pthread_mutex_t *mutex, int n)
{
struct s_duck *new;
struct s_duck *duck;
int i;
i = n;
duck = NULL;
while (i > 0)
{
new = malloc(sizeof(struct s_duck));
new->n = i;
new->mutex = mutex; // this is where the pointer to the mutex is stored
new->next = duck;
duck = new;
i--;
}
return (duck);
}
duck.h
#ifndef DUCK_H
# define DUCK_H
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <pthread.h>
struct s_duck
{
int n;
pthread_mutex_t *mutex;
struct s_duck *next;
};
struct s_duck *init_chain_ducks(pthread_mutex_t *mutex, int n);
#endif
如果我对互斥锁使用全局变量,它会很好地工作。但是使用结构中的指针,我会得到类似未定义的行为:
大多数时候我得到这个输出:
duck nbr 1
duck nbr 3
duck nbr 4
duck nbr 5
duck nbr 2
[2] 18914 segmentation fault (core dumped) ./a.out
段错误发生在pthread_join() 期间,但我也经常遇到这两个错误:
duck nbr 1
duck nbr 2
[wait indefinitely]
或者:
duck nbr 1
duck nbr 4
duck nbr 3
a.out: ../nptl/pthread_mutex_lock.c:81: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
[2] 20394 abort (core dumped) ./a.out
我一定是犯了一些基本错误,但我不知道在哪里。
(编译:gcc duck.c duck_chain.c -lpthread)
【问题讨论】:
-
请注意,尽管您的结构可以包含
pthread_mutex_t *,您的线程可以通过该pthread_mutex_t *访问互斥锁,但这在间接级别上似乎有点过分。一种可能的替代方法是为您的结构提供pthread_mutex_t类型的成员,而不是指向一个成员的指针。当互斥体的目的是保护结构的其他成员时,这特别有意义,但不限于这种情况。 -
好的,但是这里每个线程都接收到不同的结构(它是一个链表,元素比线程多),所以如果它们包含一个
pthread_mutex_t,那不起作用?还是我错过了什么? -
你是对的。如果每个线程接收到不同的结构,但它们需要访问同一个互斥锁,则该互斥锁本身不能成为该结构的成员,而指向它的指针可以。我想用你的代码我会坚持使用全局互斥锁,或者创建一个更高级别的结构来表示整个链表,并将互斥锁放在那里。
-
a higher-level structure to represent the whole linked list,是的,我确实可以这样做