con*_*ong 6 c linux mutex pthreads race-condition
我阅读了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);
}
}
Run Code Online (Sandbox Code Playgroud)
在和foo_rele之间存在竞争条件:B 线程可以在A 线程之间和中调用,这将导致未定义的行为(“尝试销毁锁定的互斥量会导致未定义的行为”)。pthread_mutex_unlockpthread_mutex_destroypthread_mutex_lockpthread_mutex_unlockpthread_mutex_destroy
我对吗?如果我是对的,那么,如何使其正常工作或如何使用 安全正确地销毁 Linux 中的互斥锁pthread_mutex_destroy?
POSIX 规范pthread_mutex_destroy()说:
\n\n\n销毁已解锁的初始化互斥锁应该是安全的。
\n
这意味着,如果线程 B在 then语句的子句pthread_mutex_unlock()中调用,则线程 A 的调用是安全的,因为它只能在线程 B 的调用解锁互斥体之后才能到达那里。elseiffoo_rele()pthread_mutex_destroy()pthread_mutex_unlock()
所有这些都假设引用计数是正确的,这样在线程 A 解锁互斥锁后,其他线程无法将计数从 0 增加到 1。换句话说,当引用计数降至 0 时,不可能有另一个线程可能调用foo_hold().
APUE 在示例代码后面的解释中提到了这一点:
\n\n\n\n在此示例中,我们忽略了线程 \xef\xac\x81 在调用之前如何获取对象
\nfoo_hold。即使引用计数为零,foo_rele如果另一个线程在调用foo_hold. 我们可以通过确保在释放内存之前可以找到该对象\xe2\x80\x99来避免这个问题。我们\xe2\x80\x99将在下面的示例中看到如何执行此操作。
| 归档时间: |
|
| 查看次数: |
3627 次 |
| 最近记录: |