我读到了 APUE 3rd , 11.6.1 Mutexes, 本章有一个关于锁定和解锁互斥锁的例子:
struct foo {
int f_count;
pthread_mutex_t f_lock;
int f_id;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(int id) /* allocate the object */
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
/* ... continue initialization ... */
}
return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) { /* last reference */
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
在foo_rele
中,pthread_mutex_unlock
和pthread_mutex_destroy
之间存在竞争条件:B线程可以调用pthread_mutex_lock
在 pthread_mutex_unlock
和 pthread_mutex_destroy
之间 A thread 这将导致未定义的行为(“试图销毁锁定的互斥量导致未定义行为”)。
我说的对吗?如果我是对的,那么,如何让它正常工作或如何在 Linux 中使用 pthread_mutex_destroy
安全正确地销毁互斥体?
最佳答案
pthread_mutex_destroy()
的 POSIX 规范说:
It shall be safe to destroy an initialized mutex that is unlocked.
这意味着如果线程 B 调用 pthread_mutex_unlock()
在else
if
的条款foo_rele()
中的声明那么线程 A 调用 pthread_mutex_destroy()
是安全的因为它只能在线程 B 的 pthread_mutex_unlock()
之后到达那里调用已解锁互斥量。
所有这些都假设引用计数是正确的,这样在线程 A 解锁互斥量后,其他线程无法从 0 -> 1 递增计数。换句话说,在引用计数下降到 0 时,不可能有另一个线程可能调用 foo_hold()
。 .
APUE 在示例代码之后的解释中提到了这一点:
In this example, we have ignored how threads find an object before calling
foo_hold
. Even though the reference count is zero, it would be a mistake forfoo_rele
to free the object’s memory if another thread is blocked on the mutex in a call tofoo_hold
. We can avoid this problem by ensuring that the object can’t be found before freeing its memory. We’ll see how to do this in the examples that follow.
关于c - 如何使用 pthread_mutex_destroy 在 Linux 中安全正确地销毁互斥量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46345261/