Reputation: 1765
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);
}
Upvotes: 4
Views: 4770
Reputation: 43688
There's not enough information given to give a really good answer. How is s
"published" to other threads? How do other threads "subscribe" to s
? In what data structure are struct 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).
In your example, neither th1
nor th2
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.
Upvotes: 4
Reputation: 234384
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.
Upvotes: 2
Reputation: 72605
It depends on what other operations you may have on s
. For example, another thread modifying value of s->c
depending on what s->i
is:
if (s->i == 1) {
s->c = 'x';
} else {
s->c = 'y';
}
In this case you cannot omit the mutex lock otherwise you may have both s->i
set to 1 and s->c
set to 'y'.
Upvotes: 2
Reputation: 10395
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.
Upvotes: 4