指针变量周围是否需要互斥锁?
涉及指针间接(其中指针指向属于关键部分的数据)的代码部分是否需要互斥锁?示例代码:
struct list {
int i;
struct list *next;
};
int modify_second_elem(struct list *head, int val);
void * func1(void *ptr);
void * func2(void *ptr);
int modify_second_elem(struct list *head, int val) {
if(head == NULL)
return 1;
/* Check to see if second element exists.
Here, I am using indirection to get the next pointer.
Would I need synchronization here? */
if(head->next == NULL)
return -1;
pthread_mutex_lock(&list_lock);
(head->next)->i = val;
pthread_mutex_unlock(&list_lock);
return 0;
}
void * func1(void *ptr) {
struct list *head;
head = (struct list *) ptr;
modify_second_elem(head, 4);
}
void * func2(void *ptr) {
struct list *head;
head = (struct list *) ptr;
modify_second_elem(head, 6);
}
void main() {
struct list *el1, *el2, *el3;
pthread_t th1, th2;
el1 = (struct list *) malloc(sizeof(list));
el2 = (struct list *) malloc(sizeof(list));
el3 = (struct list *) malloc(sizeof(list));
el1->i = 1;
el1->next = el2;
el2->i = 2;
el2->next = el3;
el3->i = 3;
el3->next = NULL;
pthread_create(&th1, NULL, &func1, (void *) el1);
pthread_create(&th2, NULL, &func2, (void *) el1);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
exit(EXIT_SUCCESS);
}
Is a mutex lock needed around a section of code that involves pointer indirection (where the pointer points to data that is part of a critical section)? An example code:
struct list {
int i;
struct list *next;
};
int modify_second_elem(struct list *head, int val);
void * func1(void *ptr);
void * func2(void *ptr);
int modify_second_elem(struct list *head, int val) {
if(head == NULL)
return 1;
/* Check to see if second element exists.
Here, I am using indirection to get the next pointer.
Would I need synchronization here? */
if(head->next == NULL)
return -1;
pthread_mutex_lock(&list_lock);
(head->next)->i = val;
pthread_mutex_unlock(&list_lock);
return 0;
}
void * func1(void *ptr) {
struct list *head;
head = (struct list *) ptr;
modify_second_elem(head, 4);
}
void * func2(void *ptr) {
struct list *head;
head = (struct list *) ptr;
modify_second_elem(head, 6);
}
void main() {
struct list *el1, *el2, *el3;
pthread_t th1, th2;
el1 = (struct list *) malloc(sizeof(list));
el2 = (struct list *) malloc(sizeof(list));
el3 = (struct list *) malloc(sizeof(list));
el1->i = 1;
el1->next = el2;
el2->i = 2;
el2->next = el3;
el3->i = 3;
el3->next = NULL;
pthread_create(&th1, NULL, &func1, (void *) el1);
pthread_create(&th2, NULL, &func2, (void *) el1);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
exit(EXIT_SUCCESS);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
没有提供足够的信息来给出真正好的答案。
s
如何“发布”到其他线程?其他线程如何“订阅”s
? struct 对象存储在什么数据结构中?因此,我将给出一个通用的答案:
线程之间共享的每种数据都需要同步。这包括共享指针。
关于指针:
您可能听说过,在一些常见的 CPU 上,正确对齐的指针的加载/存储是原子的(并非所有 CPU 或所有类型的指针都是如此,例如:x86 上的远指针是非原子的)。如果您对 CPU/VM 内存模型没有透彻的了解,请远离使用此方法,如果您不采用锁,则可能会出现许多微妙的问题(锁提供了相当强的保证)。
编辑:
在您的示例中,
th1
和th2
都不会修改列表,它们只修改列表的元素。因此,在这种特定情况下,您不需要锁定列表,只需锁定列表的元素(指针概念上属于链表实现)。在更典型的情况下,一些线程将遍历列表,而其他线程将修改列表(添加和删除元素)。这需要锁定列表,或者使用某种无锁算法。
有多种方法可以实现这种锁定。
There's not enough information given to give a really good answer. How is
s
"published" to other threads? How do other threads "subscribe" tos
? In what data structure arestruct s
objects stored?So, I'll give a generic answer:
Every kind of data that is shared between threads needs synchronization. This includes shared pointers.
About pointers:
You may have heard that on some commonplace CPUs loads/stores of correctly aligned pointers are atomic (this is not the case for all CPUs or for all kinds of pointers, e.g: far pointers on x86 are non-atomic). Stay away from using this if you don't have a thorough understanding of your CPU/VM memory model, there are many subtle things that can go wrong if you don't take locks (locks provide pretty strong guarantees).
Edit:
In your example, neither
th1
north2
modifies the list, they only modify elements of the list. So, in this specific case, you don't need to lock the list, you just need to lock elements of the list (the pointer conceptually belongs to the linked list implementation).In more typical cases, some threads would be traversing the list, while others would be modifying the list (adding and removing elements). This requires locking the list, or using some kind of lock-free algorithm.
There are several ways of doing this locking.
锁用于保护代码中的关键部分。如果您的变量位于临界区,那么您将需要使用某种锁来保护它。
Locks are used to protect critical section in the code. If your variable is in critical section, then you will need to protect it with some kind of lock.
这取决于您对
s
可能进行的其他操作。例如,另一个线程根据s->i
修改s->c
的值:在这种情况下,您不能省略互斥锁,否则您可能会遇到
s->i
均设置为 1,s->c
均设置为“y”。It depends on what other operations you may have on
s
. For example, another thread modifying value ofs->c
depending on whats->i
is:In this case you cannot omit the mutex lock otherwise you may have both
s->i
set to 1 ands->c
set to 'y'.锁用于保护关键部分。它与变量是否是指针无关。
就您而言,您不需要锁定该支票。由于
s
是一个参数,因此无法从函数外部访问它。但是,它指向的数据对于您的函数来说不是本地的,因此您可能需要锁定对该数据的访问。A lock is used to protect critical sections. It has nothing to do with a variable being a pointer or not.
In your case, you don't need to lock that check. Because
s
is a parameter it cannot be accessed from outside your function. However, the data pointed by it is not local to your function, so you might need to lock access to that data.