I understand that shared variables should be locked when multiple threads are reading or writing it at the same time to avoid concurrency issue. However, in a single writer multiple reader environment, I suspect the necessity for the writer thread to lock that variable when it is reading from it. My reasoning is that since it is the only writer, no other threads might modify the content, so it is impossible to get undefined behavior.
In other words, is read lock really necessary in my_read_1
? What are the consequences if it is omitted?
/********* Thread A *********/
hlist_head_t g_my_table[MY_TABLE_SIZE];
pthread_rwlock_t g_my_lock;
void my_update(uint64_t hash, hlist_node_t *node)
{
pthread_rwlock_wrlock(&g_my_lock);
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
hlist_add_head(node, head);
pthread_rwlock_unlock(&g_my_lock);
}
void my_read_1(uint64_t hash)
{
// TODO: is read lock necessary here?
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
if (hlist_empty(head)) {
printf("empty\n");
} else {
printf("%p %p\n", head->first->next, head->first->pprev);
}
}
/********* Thread B *********/
extern hlist_head_t g_my_table[MY_TABLE_SIZE];
extern pthread_rwlock_t g_my_lock;
void my_read_2(uint64_t hash)
{
pthread_rwlock_rdlock(&g_my_lock);
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
if (hlist_empty(head)) {
printf("empty\n");
} else {
printf("%p %p\n", head->first->next, head->first->pprev);
}
pthread_rwlock_unlock(&g_my_lock);
}
I understand that shared variables should be locked when multiple threads are reading or writing it at the same time to avoid concurrency issue. However, in a single writer multiple reader environment, I suspect the necessity for the writer thread to lock that variable when it is reading from it. My reasoning is that since it is the only writer, no other threads might modify the content, so it is impossible to get undefined behavior.
In other words, is read lock really necessary in my_read_1
? What are the consequences if it is omitted?
/********* Thread A *********/
hlist_head_t g_my_table[MY_TABLE_SIZE];
pthread_rwlock_t g_my_lock;
void my_update(uint64_t hash, hlist_node_t *node)
{
pthread_rwlock_wrlock(&g_my_lock);
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
hlist_add_head(node, head);
pthread_rwlock_unlock(&g_my_lock);
}
void my_read_1(uint64_t hash)
{
// TODO: is read lock necessary here?
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
if (hlist_empty(head)) {
printf("empty\n");
} else {
printf("%p %p\n", head->first->next, head->first->pprev);
}
}
/********* Thread B *********/
extern hlist_head_t g_my_table[MY_TABLE_SIZE];
extern pthread_rwlock_t g_my_lock;
void my_read_2(uint64_t hash)
{
pthread_rwlock_rdlock(&g_my_lock);
hlist_head_t *head = &g_my_table[hash % MY_TABLE_SIZE];
if (hlist_empty(head)) {
printf("empty\n");
} else {
printf("%p %p\n", head->first->next, head->first->pprev);
}
pthread_rwlock_unlock(&g_my_lock);
}
Share
Improve this question
asked Mar 25 at 11:51
davidhcefxdavidhcefx
3053 silver badges13 bronze badges
3
|
1 Answer
Reset to default 2In other words, is read lock really necessary in my_read_1 ? What are the consequences if it is omitted?
The requirement that must be satisfied is that every pair of accesses (reads or writes) to an object must be properly ordered if at least one of them is a write. The limitation of this requirement to the cases where at least one access is a write is what makes read / write locks sensible -- reads don't need to be synchronized with respect to each other, only with respect to writes.
Accesses by different threads are ordered via synchronization objects, such as locks. A read / write lock provides for ordering pairs of writes and pairs of one read and one write, without requiring or providing for ordering of pairs of reads. This can be advantageous.
But notwithstanding the general use of locking by a program, every pair of access by the same thread is ordered by the single-thread execution order of the program, so a thread does not need to use locking to order its own reads and writes with respect to each other. Therefore, if only one thread ever writes to the shared data then that thread does not need to use locking to protect its reads of that data.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744198431a4562765.html
my_read_1
is declared under the heading,***Thread A***
. OTOH, if I were writing it, I would either have it lock the mutex anyway, or else I would declare it under a block comment that said,WARNING! my_read_1 must only be called be called by Thread A because...
But, since I don't like to see comments in code if the need can be eliminated by changing the code itself, and since it's less typing, I almost certainly would just have it lock the mutex. – Solomon Slow Commented Mar 25 at 12:39unsigned i = 255u; ++i; printf("0x%x\n", i);
can only print 0x100, never 0x0 or 0x101.) – Eric Postpischil Commented Mar 25 at 13:43